STATIC_OVL void slime_dialogue() { register long i = (Slimed & TIMEOUT) / 2L; if (((Slimed & TIMEOUT) % 2L) && i >= 0L && i < SIZE(slime_texts)) { const char *str = slime_texts[SIZE(slime_texts) - i - 1L]; if (index(str, '%')) { if (i == 4L) { /* "you are turning green" */ if (!Blind) /* [what if you're already green?] */ pline(str, hcolor(NH_GREEN)); } else pline(str, an(Hallucination ? rndmonnam() : "green slime")); } else pline(str); } if (i == 3L) { /* limbs becoming oozy */ HFast = 0L; /* lose intrinsic speed */ stop_occupation(); if (multi > 0) nomul(0, 0); } exercise(A_DEX, FALSE); }
static void handle_occupation(void) { if ((*occupation)() == 0) occupation = NULL; if (monster_nearby()) { stop_occupation(); reset_eat(); } }
bool hitu(struct monst *mtmp, int dam) { bool res; int tmp; nomul(0); if (u.uswallow) return (0); if (mtmp->mhide && mtmp->mundetected) { mtmp->mundetected = 0; if (!Blind) { struct obj *obj; if ((obj = o_at(mtmp->mx, mtmp->my)) != NULL) pline("%s was hidden under %s!", Xmonnam(mtmp), doname(obj)); } } tmp = u.uac; /* give people with Ac = -10 at least some vulnerability */ if (tmp < 0) { dam += tmp; /* decrease damage */ if (dam <= 0) dam = 1; tmp = -rn2(-tmp); } tmp += mtmp->data->mlevel; if (multi < 0) tmp += 4; if ((Invis && mtmp->data->mlet != 'I') || !mtmp->mcansee) tmp -= 2; if (mtmp->mtrapped) tmp -= 2; if (tmp <= rnd(20)) { if (Blind) pline("It misses."); else pline("%s misses.", Monnam(mtmp)); res = 0; } else { if (Blind) pline("It hits!"); else pline("%s hits!", Monnam(mtmp)); losehp_m(dam, mtmp); res = 1; } stop_occupation(); return (res); }
/* called with dx = dy = 0 with vertical bolts */ void buzz(int type, xchar sx, xchar sy, int dx, int dy) { int abstype = abs(type); const char *fltxt = (type == -1) ? "blaze of fire" : fl[abstype]; struct rm *lev; xchar range; struct monst *mon; if(u.uswallow) { int tmp; if(type < 0) return; tmp = zhit(u.ustuck, type); pline("The %s rips into %s%s", fltxt, monnam(u.ustuck), exclam(tmp)); return; } if(type < 0) pru(); range = rn1(7,7); Tmp_at(-1, dirlet(dx,dy)); /* open call */ while(range-- > 0) { sx += dx; sy += dy; if((lev = &levl[sx][sy])->typ) Tmp_at(sx,sy); else { int bounce = 0; if(cansee(sx-dx,sy-dy)) pline("The %s bounces!", fltxt); if(ZAP_POS(levl[sx][sy-dy].typ)) bounce = 1; if(ZAP_POS(levl[sx-dx][sy].typ)) { if(!bounce || rn2(2)) bounce = 2; } switch(bounce){ case 0: dx = -dx; dy = -dy; continue; case 1: dy = -dy; sx -= dx; break; case 2: dx = -dx; sy -= dy; break; } Tmp_at(-2,dirlet(dx,dy)); continue; } if(lev->typ == POOL && abstype == 1 /* fire */) { range -= 3; lev->typ = ROOM; if(cansee(sx,sy)) { mnewsym(sx,sy); pline("The water evaporates."); } else pline("You hear a hissing sound."); } if((mon = m_at(sx,sy)) && (type != -1 || mon->data->mlet != 'D')) { wakeup(mon); if(rnd(20) < 18 + mon->data->ac) { int tmp = zhit(mon,abstype); if(mon->mhp < 1) { if(type < 0) { if(cansee(mon->mx,mon->my)) pline("%s is killed by the %s!", Monnam(mon), fltxt); mondied(mon); } else killed(mon); } else hit(fltxt, mon, exclam(tmp)); range -= 2; } else miss(fltxt,mon); } else if(sx == u.ux && sy == u.uy) { nomul(0); if(rnd(20) < 18+u.uac) { int dam = 0; range -= 2; pline("The %s hits you!",fltxt); switch(abstype) { case 0: dam = d(2,6); break; case 1: if(Fire_resistance) pline("You don't feel hot!"); else dam = d(6,6); if(!rn2(3)) burn_scrolls(); break; case 2: nomul(-rnd(25)); /* sleep ray */ break; case 3: if(Cold_resistance) pline("You don't feel cold!"); else dam = d(6,6); break; case 4: u.uhp = -1; } losehp(dam,fltxt); } else pline("The %s whizzes by you!",fltxt); stop_occupation(); } if(!ZAP_POS(lev->typ)) { int bounce = 0, rmn; if(cansee(sx,sy)) pline("The %s bounces!",fltxt); range--; if(!dx || !dy || !rn2(20)){ dx = -dx; dy = -dy; } else { if(ZAP_POS(rmn = levl[sx][sy-dy].typ) && (IS_ROOM(rmn) || ZAP_POS(levl[sx+dx][sy-dy].typ))) bounce = 1; if(ZAP_POS(rmn = levl[sx-dx][sy].typ) && (IS_ROOM(rmn) || ZAP_POS(levl[sx-dx][sy+dy].typ))) if(!bounce || rn2(2)) bounce = 2; switch(bounce){ case 0: dy = -dy; dx = -dx; break; case 1: dy = -dy; break; case 2: dx = -dx; break; } Tmp_at(-2, dirlet(dx,dy)); } } } Tmp_at(-1,-1); }
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 when something was stolen (or at least, when N should flee now) * Returns -1 if the monster died in the attempt * Avoid stealing the object stealoid */ int steal(struct monst *mtmp, char *objnambuf) { struct obj *otmp; int tmp, could_petrify, named = 0, armordelay; boolean monkey_business; /* true iff an animal is doing the thievery */ if (objnambuf) *objnambuf = '\0'; /* the following is true if successful on first of two attacks. */ if (!monnear(mtmp, u.ux, u.uy)) return 0; /* food being eaten might already be used up but will not have been removed from inventory yet; we don't want to steal that, so this will cause it to be removed now */ if (occupation) maybe_finished_meal(FALSE); if (!invent || (inv_cnt() == 1 && uskin)) { nothing_to_steal: /* Not even a thousand men in armor can strip a naked man. */ if (Blind) pline("Somebody tries to rob you, but finds nothing to steal."); else pline("%s tries to rob you, but there is nothing to steal!", Monnam(mtmp)); return 1; /* let her flee */ } /* Monkey or mugger robbing you. You don't wanna be charmed/seduced by a mugger. */ monkey_business = is_robber(mtmp->data); if (monkey_business) { ; /* skip ring special cases */ } else if (Adornment & LEFT_RING) { otmp = uleft; goto gotobj; } else if (Adornment & RIGHT_RING) { otmp = uright; goto gotobj; } tmp = 0; for (otmp = invent; otmp; otmp = otmp->nobj) if ((!uarm || otmp != uarmc) && otmp != uskin #ifdef INVISIBLE_OBJECTS && (!otmp->oinvis || perceives(mtmp->data)) #endif ) tmp += ((otmp->owornmask & (W_ARMOR | W_RING | W_AMUL | W_TOOL)) ? 5 : 1); if (!tmp) goto nothing_to_steal; tmp = rn2(tmp); for (otmp = invent; otmp; otmp = otmp->nobj) if ((!uarm || otmp != uarmc) && otmp != uskin #ifdef INVISIBLE_OBJECTS && (!otmp->oinvis || perceives(mtmp->data)) #endif ) if ((tmp -= ((otmp->owornmask & (W_ARMOR | W_RING | W_AMUL | W_TOOL)) ? 5 : 1)) < 0) break; if (!otmp) { warning("Steal fails!"); return 0; } /* can't steal gloves while wielding - so steal the wielded item. */ if (otmp == uarmg && uwep) otmp = uwep; /* can't steal armor while wearing cloak - so steal the cloak. */ else if (otmp == uarm && uarmc) otmp = uarmc; else if (otmp == uarmu && uarmc) otmp = uarmc; else if (otmp == uarmu && uarm) otmp = uarm; gotobj: if (otmp->o_id == stealoid) return 0; /* animals can't overcome curse stickiness nor unlock chains */ if (monkey_business) { boolean ostuck; /* is the player prevented from voluntarily giving up this item? (ignores loadstones; the !can_carry() check will catch those) */ if (otmp == uball) ostuck = TRUE; /* effectively worn; curse is implicit */ else if (otmp == uquiver || (otmp == uswapwep && !u.twoweap)) ostuck = FALSE; /* not really worn; curse doesn't matter */ else ostuck = (otmp->cursed && otmp->owornmask); if (ostuck || !can_carry(mtmp, otmp)) { static const char * const how[] = { "steal","snatch","grab","take" }; cant_take: pline("%s tries to %s your %s but gives up.", Monnam(mtmp), how[rn2(SIZE(how))], (otmp->owornmask & W_ARMOR) ? equipname(otmp) : cxname(otmp)); /* the fewer items you have, the less likely the thief is going to stick around to try again (0) instead of running away (1) */ return !rn2(inv_cnt() / 5 + 2); } } if (otmp->otyp == LEASH && otmp->leashmon) { if (monkey_business && otmp->cursed) goto cant_take; o_unleash(otmp); } /* you're going to notice the theft... */ stop_occupation(); if ((otmp->owornmask & (W_ARMOR | W_RING | W_AMUL | W_TOOL))){ switch(otmp->oclass) { case TOOL_CLASS: case AMULET_CLASS: case RING_CLASS: case FOOD_CLASS: /* meat ring */ remove_worn_item(otmp, TRUE); break; case ARMOR_CLASS: armordelay = objects[otmp->otyp].oc_delay; /* Stop putting on armor which has been stolen. */ if (donning(otmp)) { remove_worn_item(otmp, TRUE); break; } else if (monkey_business) { /* animals usually don't have enough patience to take off items which require extra time */ if (armordelay >= 1 && rn2(10)) goto cant_take; remove_worn_item(otmp, TRUE); break; } else { int curssv = otmp->cursed; int slowly; boolean seen = canspotmon(level, mtmp); otmp->cursed = 0; /* can't charm you without first waking you */ if (multi < 0 && is_fainted()) unmul(NULL); slowly = (armordelay >= 1 || multi < 0); if (flags.female) pline("%s charms you. You gladly %s your %s.", !seen ? "She" : Monnam(mtmp), curssv ? "let her take" : slowly ? "start removing" : "hand over", equipname(otmp)); else pline("%s seduces you and %s off your %s.", !seen ? "She" : Adjmonnam(mtmp, "beautiful"), curssv ? "helps you to take" : slowly ? "you start taking" : "you take", equipname(otmp)); named++; /* the following is to set multi for later on */ nomul(-armordelay, "taking off clothes"); remove_worn_item(otmp, TRUE); otmp->cursed = curssv; if (multi < 0){ /* multi = 0; nomovemsg = 0; afternmv = 0; */ stealoid = otmp->o_id; stealmid = mtmp->m_id; afternmv = stealarm; return 0; } } break; default: warning("Tried to steal a strange worn thing. [%d]", otmp->oclass); } } else if (otmp->owornmask) remove_worn_item(otmp, TRUE); /* do this before removing it from inventory */ if (objnambuf) strcpy(objnambuf, yname(otmp)); /* set mavenge bit so knights won't suffer an * alignment penalty during retaliation; */ mtmp->mavenge = 1; freeinv(otmp); pline("%s stole %s.", named ? "She" : Monnam(mtmp), doname(otmp)); could_petrify = (otmp->otyp == CORPSE && touch_petrifies(&mons[otmp->corpsenm])); mpickobj(mtmp,otmp); /* may free otmp */ if (could_petrify && !(mtmp->misc_worn_check & W_ARMG)) { minstapetrify(mtmp, TRUE); return -1; } return (multi < 0) ? 0 : 1; }
void nh_timeout() { register struct prop *upp; int sleeptime; int m_idx; int baseluck = (flags.moonphase == FULL_MOON) ? 1 : 0; if (flags.friday13) baseluck -= 1; if (u.uluck != baseluck && moves % (u.uhave.amulet || u.ugangr ? 300 : 600) == 0) { /* Cursed luckstones stop bad luck from timing out; blessed luckstones * stop good luck from timing out; normal luckstones stop both; * neither is stopped if you don't have a luckstone. * Luck is based at 0 usually, +1 if a full moon and -1 on Friday 13th */ register int time_luck = stone_luck(FALSE); boolean nostone = !carrying(LUCKSTONE) && !stone_luck(TRUE); if(u.uluck > baseluck && (nostone || time_luck < 0)) u.uluck--; else if(u.uluck < baseluck && (nostone || time_luck > 0)) u.uluck++; } if(u.uinvulnerable) return; /* things past this point could kill you */ if(Stoned) stoned_dialogue(); if(Slimed) slime_dialogue(); if(Vomiting) vomiting_dialogue(); if(Strangled) choke_dialogue(); if(u.mtimedone && !--u.mtimedone) { if (Unchanging) u.mtimedone = rnd(100*youmonst.data->mlevel + 1); else rehumanize(); } if(u.ucreamed) u.ucreamed--; /* Dissipate spell-based protection. */ if (u.usptime) { if (--u.usptime == 0 && u.uspellprot) { u.usptime = u.uspmtime; u.uspellprot--; find_ac(); if (!Blind) Norep("The %s haze around you %s.", hcolor(NH_GOLDEN), u.uspellprot ? "becomes less dense" : "disappears"); } } #ifdef STEED if (u.ugallop) { if (--u.ugallop == 0L && u.usteed) pline("%s stops galloping.", Monnam(u.usteed)); } #endif for(upp = u.uprops; upp < u.uprops+SIZE(u.uprops); upp++) if((upp->intrinsic & TIMEOUT) && !(--upp->intrinsic & TIMEOUT)) { switch(upp - u.uprops){ case STONED: if (delayed_killer && !killer) { killer = delayed_killer; delayed_killer = 0; } if (!killer) { /* leaving killer_format would make it "petrified by petrification" */ killer_format = NO_KILLER_PREFIX; killer = "killed by petrification"; } done(STONING); break; case SLIMED: if (delayed_killer && !killer) { killer = delayed_killer; delayed_killer = 0; } if (!killer) { killer_format = NO_KILLER_PREFIX; killer = "turned into green slime"; } done(TURNED_SLIME); break; case VOMITING: make_vomiting(0L, TRUE); break; case SICK: You("die from your illness."); killer_format = KILLED_BY_AN; killer = u.usick_cause; if ((m_idx = name_to_mon(killer)) >= LOW_PM) { if (type_is_pname(&mons[m_idx])) { killer_format = KILLED_BY; } else if (mons[m_idx].geno & G_UNIQ) { killer = the(killer); Strcpy(u.usick_cause, killer); killer_format = KILLED_BY; } } u.usick_type = 0; done(POISONING); break; case FAST: if (!Very_fast) You_feel("yourself slowing down%s.", Fast ? " a bit" : ""); break; case CONFUSION: HConfusion = 1; /* So make_confused works properly */ make_confused(0L, TRUE); stop_occupation(); break; case STUNNED: HStun = 1; make_stunned(0L, TRUE); stop_occupation(); break; case BLINDED: Blinded = 1; make_blinded(0L, TRUE); stop_occupation(); break; case INVIS: newsym(u.ux,u.uy); if (!Invis && !BInvis && !Blind) { You(!See_invisible ? "are no longer invisible." : "can no longer see through yourself."); stop_occupation(); } break; case SEE_INVIS: set_mimic_blocking(); /* do special mimic handling */ see_monsters(); /* make invis mons appear */ newsym(u.ux,u.uy); /* make self appear */ stop_occupation(); break; case WOUNDED_LEGS: heal_legs(); stop_occupation(); break; case HALLUC: HHallucination = 1; (void) make_hallucinated(0L, TRUE, 0L); stop_occupation(); break; case SLEEPING: if (unconscious() || Sleep_resistance) HSleeping += rnd(100); else if (Sleeping) { You("fall asleep."); sleeptime = rnd(20); fall_asleep(-sleeptime, TRUE); HSleeping += sleeptime + rnd(100); } break; case LEVITATION: (void) float_down(I_SPECIAL|TIMEOUT, 0L); break; case STRANGLED: killer_format = KILLED_BY; killer = (u.uburied) ? "suffocation" : "strangulation"; done(DIED); break; case FUMBLING: /* call this only when a move took place. */ /* otherwise handle fumbling msgs locally. */ if (u.umoved && !Levitation) { slip_or_trip(); nomul(-2, "fumbling"); nomovemsg = ""; /* The more you are carrying the more likely you * are to make noise when you fumble. Adjustments * to this number must be thoroughly play tested. */ if ((inv_weight() > -500)) { You("make a lot of noise!"); wake_nearby(); } } /* from outside means slippery ice; don't reset counter if that's the only fumble reason */ HFumbling &= ~FROMOUTSIDE; if (Fumbling) HFumbling += rnd(20); break; case DETECT_MONSTERS: see_monsters(); break; case PREGNANT: { char buf[BUFSZ]; if (!flags.female) { strcpy(buf, body_part(STOMACH)); if (!strcmp(buf, "stomach")) strcpy(buf, "belly"); pline("Something bursts out of your %s!"); killer_format = KILLED_BY; killer = "male childbirth"; done(DIED); } mksobj_at(PLACENTA, u.ux, u.uy, FALSE, FALSE); pline("BABIES!"); /* TODO */ stop_occupation(); break; } } } run_timers(); }
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); } }
// returns 1 when something was stolen // (or at least, when N should flee now) // avoid stealing the object stealoid int steal(struct monst *mtmp) { struct obj *otmp; int tmp; int named = 0; if (!invent) { if (Blind) pline("Somebody tries to rob you, but finds nothing to steal."); else pline("%s tries to rob you, but she finds nothing to steal!", Monnam(mtmp)); return 1; // let her flee } tmp = 0; for (otmp = invent; otmp; otmp = otmp->nobj) if (otmp != uarm2) tmp += ((otmp->owornmask & (W_ARMOR | W_RING)) ? 5 : 1); tmp = rn2(tmp); for (otmp = invent; otmp; otmp = otmp->nobj) if (otmp != uarm2) if ((tmp -= ((otmp->owornmask & (W_ARMOR | W_RING)) ? 5 : 1)) < 0) break; if (!otmp) { impossible("Steal fails!"); return 0; } if (otmp->o_id == stealoid) return 0; if ((otmp->owornmask & (W_ARMOR | W_RING))) { switch (otmp->olet) { case RING_SYM: ringoff(otmp); break; case ARMOR_SYM: if (multi < 0 || otmp == uarms) { setworn((struct obj *) 0, otmp->owornmask & W_ARMOR); break; } { int curssv = otmp->cursed; otmp->cursed = 0; stop_occupation(); pline("%s seduces you and %s off your %s.", Amonnam(mtmp, Blind ? "gentle" : "beautiful"), otmp->cursed ? "helps you to take" : "you start taking", (otmp == uarmg) ? "gloves" : (otmp == uarmh) ? "helmet" : "armor"); named++; (void) armoroff(otmp); otmp->cursed = curssv; if (multi < 0) { // multi = 0; // nomovemsg = 0; // afternmv = 0; stealoid = otmp->o_id; stealmid = mtmp->m_id; afternmv = stealarm; return 0; } break; } default: impossible("Tried to steal a strange worn thing."); } } else if (otmp == uwep) setuwep((struct obj *) 0); if (otmp->olet == CHAIN_SYM) { impossible("How come you are carrying that chain?"); } if (Punished && otmp == uball) { Punished = 0; freeobj(uchain); free((char *) uchain); uchain = (struct obj *) 0; uball->spe = 0; uball = (struct obj *) 0; // superfluous } freeinv(otmp); pline("%s stole %s.", named ? "She" : Monnam(mtmp), doname(otmp)); mpickobj(mtmp, otmp); return multi < 0 ? 0 : 1; }
int main(int argc, char *argv[]) { int fd; #ifdef CHDIR char *dir; #endif hname = argv[0]; hackpid = getpid(); #ifdef CHDIR /* otherwise no chdir() */ /* * See if we must change directory to the playground. * (Perhaps hack runs suid and playground is inaccessible * for the player.) * The environment variable HACKDIR is overridden by a * -d command line option (must be the first option given) */ dir = getenv("HACKDIR"); if (argc > 1 && !strncmp(argv[1], "-d", 2)) { argc--; argv++; dir = argv[0] + 2; if (*dir == '=' || *dir == ':') dir++; if (!*dir && argc > 1) { argc--; argv++; dir = argv[0]; } if (!*dir) error("Flag -d must be followed by a directory name."); } #endif /* * Who am i? Algorithm: 1. Use name as specified in HACKOPTIONS * 2. Use $USER or $LOGNAME (if 1. fails) * 3. Use getlogin() (if 2. fails) * The resulting name is overridden by command line options. * If everything fails, or if the resulting name is some generic * account like "games", "play", "player", "hack" then eventually * we'll ask him. * Note that we trust him here; it is possible to play under * somebody else's name. */ { char *s; initoptions(); if (!*plname && (s = getenv("USER"))) strncpy(plname, s, sizeof(plname) - 1); if (!*plname && (s = getenv("LOGNAME"))) strncpy(plname, s, sizeof(plname) - 1); if (!*plname && (s = getlogin())) strncpy(plname, s, sizeof(plname) - 1); } /* * Now we know the directory containing 'record' and * may do a prscore(). */ if (argc > 1 && !strncmp(argv[1], "-s", 2)) { #ifdef CHDIR chdirx(dir, 0); #endif prscore(argc, argv); exit(0); } /* * It seems he really wants to play. * Remember tty modes, to be restored on exit. */ gettty(); setbuf(stdout, obuf); umask(007); setrandom(); startup(); cls(); u.uhp = 1; /* prevent RIP on early quits */ u.ux = FAR; /* prevent nscr() */ signal(SIGHUP, hangup); /* * Find the creation date of this game, * so as to avoid restoring outdated savefiles. */ gethdate(hname); /* * We cannot do chdir earlier, otherwise gethdate will fail. */ #ifdef CHDIR chdirx(dir, 1); #endif /* * Process options. */ while (argc > 1 && argv[1][0] == '-') { argv++; argc--; switch (argv[0][1]) { #ifdef WIZARD case 'D': wizard = TRUE; break; #endif #ifdef NEWS case 'n': flags.nonews = TRUE; break; #endif case 'u': if (argv[0][2]) strncpy(plname, argv[0] + 2, sizeof(plname) - 1); else if (argc > 1) { argc--; argv++; strncpy(plname, argv[0], sizeof(plname) - 1); } else printf("Player name expected after -u\n"); break; default: /* allow -T for Tourist, etc. */ strncpy(pl_character, argv[0] + 1, sizeof(pl_character) - 1); } } if (argc > 1) locknum = atoi(argv[1]); #ifdef MAX_NR_OF_PLAYERS if (!locknum || locknum > MAX_NR_OF_PLAYERS) locknum = MAX_NR_OF_PLAYERS; #endif #ifdef DEF_PAGER if (!(catmore = getenv("HACKPAGER")) && !(catmore = getenv("PAGER"))) catmore = DEF_PAGER; #endif #ifdef MAIL getmailstatus(); #endif #ifdef WIZARD if (wizard) strcpy(plname, "wizard"); else #endif if (!*plname || !strncmp(plname, "player", 4) || !strncmp(plname, "games", 4)) askname(); plnamesuffix(); /* strip suffix from name; calls askname() */ /* again if suffix was whole name */ /* accepts any suffix */ #ifdef WIZARD if (!wizard) { #endif /* * check for multiple games under the same name * (if !locknum) or check max nr of players (otherwise) */ signal(SIGQUIT, SIG_IGN); signal(SIGINT, SIG_IGN); if (!locknum) strcpy(lock, plname); getlock(); /* sets lock if locknum != 0 */ #ifdef WIZARD } else { char *sfoo; strcpy(lock, plname); if ((sfoo = getenv("MAGIC"))) while (*sfoo) { switch (*sfoo++) { case 'n': srandom(*sfoo++); break; } } if ((sfoo = getenv("GENOCIDED")) != NULL) { if (*sfoo == '!') { struct permonst *pm = mons; char *gp = genocided; while (pm < mons + CMNUM + 2) { if (!strchr(sfoo, pm->mlet)) *gp++ = pm->mlet; pm++; } *gp = 0; } else strncpy(genocided, sfoo, sizeof(genocided) - 1); strcpy(fut_geno, genocided); } } #endif setftty(); sprintf(SAVEF, "save/%d%s", getuid(), plname); regularize(SAVEF + 5); /* avoid . or / in name */ if ((fd = open(SAVEF, O_RDONLY)) >= 0 && (uptodate(fd) || unlink(SAVEF) == 666)) { signal(SIGINT, done1); pline("Restoring old save file..."); fflush(stdout); if (!dorecover(fd)) goto not_recovered; pline("Hello %s, welcome to %s!", plname, gamename); flags.move = 0; } else { not_recovered: fobj = fcobj = invent = 0; fmon = fallen_down = 0; ftrap = 0; fgold = 0; flags.ident = 1; init_objects(); u_init(); signal(SIGINT, done1); mklev(); u.ux = xupstair; u.uy = yupstair; inshop(); setsee(); flags.botlx = 1; makedog(); { struct monst *mtmp; if ((mtmp = m_at(u.ux, u.uy)) != NULL) mnexto(mtmp); /* riv05!a3 */ } seemons(); #ifdef NEWS if (flags.nonews || !readnews()) /* after reading news we did docrt() already */ #endif docrt(); /* give welcome message before pickup messages */ pline("Hello %s, welcome to %s!", plname, gamename); pickup(1); read_engr_at(u.ux, u.uy); flags.move = 1; } flags.moonphase = phase_of_the_moon(); if (flags.moonphase == FULL_MOON) { pline("You are lucky! Full moon tonight."); u.uluck++; } else if (flags.moonphase == NEW_MOON) pline("Be careful! New moon tonight."); initrack(); for (;;) { if (flags.move) { /* actual time passed */ settrack(); if (moves % 2 == 0 || (!(Fast & ~INTRINSIC) && (!Fast || rn2(3)))) { movemon(); if (!rn2(70)) makemon(NULL, 0, 0); } if (Glib) glibr(); p_timeout(); ++moves; if (flags.time) flags.botl = 1; if (u.uhp < 1) { pline("You die..."); done("died"); } if (u.uhp * 10 < u.uhpmax && moves - wailmsg > 50) { wailmsg = moves; if (u.uhp == 1) pline("You hear the wailing of the Banshee..."); else pline("You hear the howling of the CwnAnnwn..."); } if (u.uhp < u.uhpmax) { if (u.ulevel > 9) { if (Regeneration || !(moves % 3)) { flags.botl = 1; u.uhp += rnd((int)u.ulevel - 9); if (u.uhp > u.uhpmax) u.uhp = u.uhpmax; } } else if (Regeneration || (!(moves % (22 - u.ulevel * 2)))) { flags.botl = 1; u.uhp++; } } if (Teleportation && !rn2(85)) tele(); if (Searching && multi >= 0) dosearch(); gethungry(); invault(); amulet(); } if (multi < 0) { if (!++multi) { pline("%s", nomovemsg ? nomovemsg : "You can move again."); nomovemsg = 0; if (afternmv) (*afternmv)(); afternmv = NULL; } } find_ac(); #ifndef QUEST if (!flags.mv || Blind) #endif { seeobjs(); seemons(); nscr(); } if (flags.botl || flags.botlx) bot(); flags.move = 1; if (multi >= 0 && occupation) { if (monster_nearby()) stop_occupation(); else if ((*occupation)() == 0) occupation = NULL; continue; } if (multi > 0) { #ifdef QUEST if (flags.run >= 4) finddir(); #endif 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 (multi && multi % 7 == 0) fflush(stdout); } }
void invault(void) { struct monst *guard; int trycount, vaultroom = (int)vault_occupied(u.urooms); if (!vaultroom) { u.uinvault = 0; return; } vaultroom -= ROOMOFFSET; guard = findgd(); if (++u.uinvault % 30 == 0 && !guard) { /* if time ok and no guard now. */ char buf[BUFSZ]; int x, y, dd, gx, gy; int lx = 0, ly = 0; /* first find the goal for the guard */ for (dd = 2; (dd < ROWNO || dd < COLNO); dd++) { for (y = u.uy - dd; y <= u.uy + dd; ly = y, y++) { if (y < 0 || y > ROWNO - 1) continue; for (x = u.ux - dd; x <= u.ux + dd; lx = x, x++) { if (y != u.uy - dd && y != u.uy + dd && x != u.ux - dd) x = u.ux + dd; if (x < 1 || x > COLNO - 1) continue; if (levl[x][y].typ == CORR) { if (x < u.ux) lx = x + 1; else if (x > u.ux) lx = x - 1; else lx = x; if (y < u.uy) ly = y + 1; else if (y > u.uy) ly = y - 1; else ly = y; if (levl[lx][ly].typ != STONE && levl[lx][ly].typ != CORR) goto incr_radius; goto fnd; } } } incr_radius: ; } impossible("Not a single corridor on this level??"); tele(); return; fnd: gx = x; gy = y; /* next find a good place for a door in the wall */ x = u.ux; y = u.uy; if (levl[x][y].typ != ROOM) { /* player dug a door and is in it */ if (levl[x + 1][y].typ == ROOM) x = x + 1; else if (levl[x][y + 1].typ == ROOM) y = y + 1; else if (levl[x - 1][y].typ == ROOM) x = x - 1; else if (levl[x][y - 1].typ == ROOM) y = y - 1; else if (levl[x + 1][y + 1].typ == ROOM) { x = x + 1; y = y + 1; } else if (levl[x - 1][y - 1].typ == ROOM) { x = x - 1; y = y - 1; } else if (levl[x + 1][y - 1].typ == ROOM) { x = x + 1; y = y - 1; } else if (levl[x - 1][y + 1].typ == ROOM) { x = x - 1; y = y + 1; } } while (levl[x][y].typ == ROOM) { int dx, dy; dx = (gx > x) ? 1 : (gx < x) ? -1 : 0; dy = (gy > y) ? 1 : (gy < y) ? -1 : 0; if (abs(gx - x) >= abs(gy - y)) x += dx; else y += dy; } if (x == u.ux && y == u.uy) { if (levl[x + 1][y].typ == HWALL || levl[x + 1][y].typ == DOOR) x = x + 1; else if (levl[x - 1][y].typ == HWALL || levl[x - 1][y].typ == DOOR) x = x - 1; else if (levl[x][y + 1].typ == VWALL || levl[x][y + 1].typ == DOOR) y = y + 1; else if (levl[x][y - 1].typ == VWALL || levl[x][y - 1].typ == DOOR) y = y - 1; else return; } /* make something interesting happen */ if (!(guard = makemon(&mons[PM_GUARD], x, y, NO_MM_FLAGS))) return; guard->isgd = 1; guard->mpeaceful = 1; set_malign(guard); EGD(guard)->gddone = 0; EGD(guard)->ogx = x; EGD(guard)->ogy = y; assign_level(&(EGD(guard)->gdlevel), &u.uz); EGD(guard)->vroom = vaultroom; EGD(guard)->warncnt = 0; reset_faint(); /* if fainted - wake up */ if (canspotmon(guard)) { char name[BUFSZ]; g_monnam(name, BUFSZ, guard); pline("Suddenly one of the Vault's %s enters!", makeplural(name)); } else { pline("Someone else has entered the Vault."); } newsym(guard->mx, guard->my); if (youmonst.m_ap_type == M_AP_OBJECT || u.uundetected) { if (youmonst.m_ap_type == M_AP_OBJECT && youmonst.mappearance != GOLD_PIECE) verbalize("Hey! Who left that %s in here?", mimic_obj_name(&youmonst)); /* You're mimicking some object or you're hidden. */ pline("Puzzled, %s turns around and leaves.", mhe(guard)); mongone(guard); return; } if (Strangled|| is_silent(youmonst.data) || multi < 0) { /* [we ought to record whether this this message has already been given in order to vary it upon repeat visits, but discarding the monster and its egd data renders that hard] */ verbalize("I'll be back when you're ready to speak to me!"); mongone(guard); return; } stop_occupation(); /* if occupied, stop it *now* */ trycount = 5; do { getlin("\"Hello stranger, who are you?\" -", buf); (void)mungspaces(buf); } while (!letter(buf[0]) && --trycount > 0); if (u.ualign.type == A_LAWFUL && /* ignore trailing text, in case player includes character's rank */ strncmpi(buf, plname, (int)strlen(plname)) != 0) { adjalign(-1); /* Liar! */ } if (!strcmpi(buf, "Croesus") || !strcmpi(buf, "Kroisos") || !strcmpi(buf, "Creosote")) { if (!mvitals[PM_CROESUS].died) { verbalize("Oh, yes, of course. Sorry to have disturbed you."); mongone(guard); } else { setmangry(guard); verbalize("Back from the dead, are you? I'll remedy that!"); /* don't want guard to waste next turn wielding a weapon */ if (!MON_WEP(guard)) { guard->weapon_check = NEED_HTH_WEAPON; (void)mon_wield_item(guard); } } return; } verbalize("I don't know you."); if (!u.ugold && !hidden_gold()) verbalize("Please follow me."); else { if (!u.ugold) verbalize("You have hidden gold."); verbalize("Most likely all your gold was stolen from this vault."); verbalize("Please drop that gold and follow me."); } EGD(guard)->gdx = gx; EGD(guard)->gdy = gy; EGD(guard)->fcbeg = 0; EGD(guard)->fakecorr[0].fx = x; EGD(guard)->fakecorr[0].fy = y; if (IS_WALL(levl[x][y].typ)) EGD(guard)->fakecorr[0].ftyp = levl[x][y].typ; else { /* the initial guard location is a dug door */ int vlt = EGD(guard)->vroom; signed char lowx = rooms[vlt].lx, hix = rooms[vlt].hx; signed char lowy = rooms[vlt].ly, hiy = rooms[vlt].hy; if (x == lowx - 1 && y == lowy - 1) EGD(guard)->fakecorr[0].ftyp = TLCORNER; else if (x == hix + 1 && y == lowy - 1) EGD(guard)->fakecorr[0].ftyp = TRCORNER; else if (x == lowx - 1 && y == hiy + 1) EGD(guard)->fakecorr[0].ftyp = BLCORNER; else if (x == hix + 1 && y == hiy + 1) EGD(guard)->fakecorr[0].ftyp = BRCORNER; else if (y == lowy - 1 || y == hiy + 1) EGD(guard)->fakecorr[0].ftyp = HWALL; else if (x == lowx - 1 || x == hix + 1) EGD(guard)->fakecorr[0].ftyp = VWALL; } levl[x][y].typ = DOOR; levl[x][y].flags = D_NODOOR; unblock_point(x, y); /* doesn't block light */ EGD(guard)->fcend = 1; EGD(guard)->warncnt = 1; } }
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(); } }