Esempio n. 1
0
int
dothrow()
{
	register struct obj *obj;

	if(check_capacity(NULL)) return(0);
	obj = getobj(toss_objs, "throw");
	/* it is also possible to throw food */
	/* (or jewels, or iron balls... ) */

	if(!obj || !getdir(NULL)) {       /* ask "in what direction?" */
		if (obj && obj->oclass == GOLD_CLASS) {
		    u.ugold += obj->quan;
		    flags.botl = 1;
		    dealloc_obj(obj);
		}
		return(0);
	}

	if(obj->oclass == GOLD_CLASS) return(throw_gold(obj));

	if(!canletgo(obj,"throw"))
		return(0);
	if (obj->oartifact == ART_MJOLLNIR && obj != uwep) {
		You("must be wielding %s in order to throw it.", xname(obj));
		return(0);
	}
	if ((obj->oartifact == ART_MJOLLNIR && ACURR(A_STR) != 125)
	   || (obj->otyp == BOULDER
#ifdef POLYSELF
					&& !throws_rocks(uasmon)
#endif
								)) {
		pline("It's too heavy.");
		return(1);
	}
	if(!u.dx && !u.dy && !u.dz) {
		You("cannot throw an object at yourself.");
		return(0);
	}
	u_wipe_engr(2);

	if(obj == uwep) {
	    if(welded(obj)) {
		weldmsg(obj, FALSE);
		return(1);
	    }
	    if(obj->quan > 1L)
		setuwep(splitobj(obj, 1L));
	    else {
		setuwep((struct obj *)0);
		if (uwep) return(1); /* unwielded, died, rewielded */
	    }
	}
	else if(obj->quan > 1L)
		(void) splitobj(obj, 1L);
	freeinv(obj);
	return(throwit(obj));
}
Esempio n. 2
0
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);
	}
    }
}
Esempio n. 3
0
int
dothrow()
{
	struct obj *obj;
	struct monst *mon;
	int tmp;

	obj = getobj("#)", "throw");   /* it is also possible to throw food */
				       /* (or jewels, or iron balls ... ) */
	if(!obj || !getdir(1))	       /* ask "in what direction?" */
		return(0);
	if(obj->owornmask & (W_ARMOR | W_RING)){
		pline("You can't throw something you are wearing.");
		return(0);
	}

	u_wipe_engr(2);

	if(obj == uwep){
		if(obj->cursed){
			pline("Your weapon is welded to your hand.");
			return(1);
		}
		if(obj->quan > 1)
			setuwep(splitobj(obj, 1));
		else
			setuwep((struct obj *) 0);
	}
	else if(obj->quan > 1)
		(void) splitobj(obj, 1);
	freeinv(obj);
	if(u.uswallow) {
		mon = u.ustuck;
		bhitpos.x = mon->mx;
		bhitpos.y = mon->my;
	} else if(u.dz) {
	  if(u.dz < 0) {
	    pline("%s hits the ceiling, then falls back on top of your head.",
		Doname(obj));		/* note: obj->quan == 1 */
	    if(obj->olet == POTION_SYM)
		potionhit(&youmonst, obj);
	    else {
		if(uarmh) pline("Fortunately, you are wearing a helmet!");
		losehp(uarmh ? 1 : rnd((int)(obj->owt)), "falling object");
		dropy(obj);
	    }
	  } else {
	    pline("%s hits the floor.", Doname(obj));
	    if(obj->otyp == EXPENSIVE_CAMERA) {
		pline("It is shattered in a thousand pieces!");
		obfree(obj, Null(obj));
	    } else if(obj->otyp == EGG) {
		pline("\"Splash!\"");
		obfree(obj, Null(obj));
	    } else if(obj->olet == POTION_SYM) {
		pline("The flask breaks, and you smell a peculiar odor ...");
		potionbreathe(obj);
		obfree(obj, Null(obj));
	    } else {
		dropy(obj);
	    }
	  }
	  return(1);
	} else if(obj->otyp == BOOMERANG) {
		mon = boomhit(u.dx, u.dy);
		if(mon == &youmonst) {		/* the thing was caught */
			(void) addinv(obj);
			return(1);
		}
	} else {
		if(obj->otyp == PICK_AXE && shkcatch(obj))
		    return(1);

		mon = bhit(u.dx, u.dy, (obj->otyp == ICE_BOX) ? 1 :
			(!Punished || obj != uball) ? 8 : !u.ustuck ? 5 : 1,
			obj->olet, NULL, NULL, obj);
	}
	if(mon) {
		/* awake monster if sleeping */
		wakeup(mon);

		if(obj->olet == WEAPON_SYM) {
			tmp = -1+u.ulevel+mon->data->ac+abon();
			if(obj->otyp < ROCK) {
				if(!uwep ||
				    uwep->otyp != obj->otyp+(BOW-ARROW))
					tmp -= 4;
				else {
					tmp += uwep->spe;
				}
			} else
			if(obj->otyp == BOOMERANG) tmp += 4;
			tmp += obj->spe;
			if(u.uswallow || tmp >= rnd(20)) {
				if(hmon(mon,obj,1) == TRUE){
				  /* mon still alive */
#ifndef NOWORM
				  cutworm(mon,bhitpos.x,bhitpos.y,obj->otyp);
#endif /* NOWORM */
				} else mon = 0;
				/* weapons thrown disappear sometimes */
				if(obj->otyp < BOOMERANG && rn2(3)) {
					/* check bill; free */
					obfree(obj, (struct obj *) 0);
					return(1);
				}
			} else miss(objects[obj->otyp].oc_name, mon);
		} else if(obj->otyp == HEAVY_IRON_BALL) {
			tmp = -1+u.ulevel+mon->data->ac+abon();
			if(!Punished || obj != uball) tmp += 2;
			if(u.utrap) tmp -= 2;
			if(u.uswallow || tmp >= rnd(20)) {
				if(hmon(mon,obj,1) == FALSE)
					mon = 0;	/* he died */
			} else miss("iron ball", mon);
		} else if(obj->olet == POTION_SYM && u.ulevel > rn2(15)) {
			potionhit(mon, obj);
			return(1);
		} else {
			if(cansee(bhitpos.x,bhitpos.y))
				pline("You miss %s.",monnam(mon));
			else pline("You miss it.");
			if(obj->olet == FOOD_SYM && mon->data->mlet == 'd')
				if(tamedog(mon,obj)) return(1);
			if(obj->olet == GEM_SYM && mon->data->mlet == 'u' &&
				!mon->mtame){
			 if(obj->dknown && objects[obj->otyp].oc_name_known){
			  if(objects[obj->otyp].g_val > 0){
			    u.uluck += 5;
			    goto valuable;
			  } else {
			    pline("%s is not interested in your junk.",
				Monnam(mon));
			  }
			 } else { /* value unknown to @ */
			    u.uluck++;
			valuable:
			    if(u.uluck > LUCKMAX)	/* dan@ut-ngp */
				u.uluck = LUCKMAX;
			    pline("%s graciously accepts your gift.",
				Monnam(mon));
			    mpickobj(mon, obj);
			    rloc(mon);
			    return(1);
			 }
			}
		}
	}
		/* the code following might become part of dropy() */
	if(obj->otyp == CRYSKNIFE)
		obj->otyp = WORM_TOOTH;
	obj->ox = bhitpos.x;
	obj->oy = bhitpos.y;
	obj->nobj = fobj;
	fobj = obj;
	/* prevent him from throwing articles to the exit and escaping */
	/* subfrombill(obj); */
	stackobj(obj);
	if(Punished && obj == uball &&
		(bhitpos.x != u.ux || bhitpos.y != u.uy)){
		freeobj(uchain);
		unpobj(uchain);
		if(u.utrap){
			if(u.utraptype == TT_PIT)
				pline("The ball pulls you out of the pit!");
			else {
			    long side =
				rn2(3) ? LEFT_SIDE : RIGHT_SIDE;
			    pline("The ball pulls you out of the bear trap.");
			    pline("Your %s leg is severely damaged.",
				(side == LEFT_SIDE) ? "left" : "right");
			    set_wounded_legs(side, 500+rn2(1000));
			    losehp(2, "thrown ball");
			}
			u.utrap = 0;
		}
		unsee();
		uchain->nobj = fobj;
		fobj = uchain;
		u.ux = uchain->ox = bhitpos.x - u.dx;
		u.uy = uchain->oy = bhitpos.y - u.dy;
		setsee();
		(void) inshop();
	}
	if(cansee(bhitpos.x, bhitpos.y)) prl(bhitpos.x,bhitpos.y);
	return(1);
}
Esempio n. 4
0
void
moveloop()
{
#ifdef MICRO
	char ch;
	int abort_lev;
#endif
	int moverate = 0;
	boolean didmove = 0;

	/* Note:  these initializers don't do anything except guarantee that
		we're linked properly.
	*/
	decl_init();
	monst_init();
	monstr_init();	/* monster strengths */
	objects_init();

	(void) encumber_msg(); /* in case they auto-picked up something */

	for(;;) {
#ifdef CLIPPING
		cliparound(u.ux, u.uy);
#endif
#if defined(MAC_MPW32) && !defined(MODEL_FAR)
		UnloadAllSegments();  /* Marks non-resident segments as purgeable */
#endif
		get_nh_event();

		didmove = flags.move;
		if(flags.move) {	/* actual time passed */
#ifdef POLYSELF
		    int oldmtimedone;
#endif
		    int wtcap;

		    if (u.utotype) deferred_goto();
		    wtcap = encumber_msg();
#ifdef POLYSELF
		    oldmtimedone = u.mtimedone;
#endif

#ifdef SOUNDS
		    dosounds();
#endif

		    if(moverate <= 0) {
			/* calculate how much time passed. */
			int moveamt = 0;
			if(Fast & ~INTRINSIC) moveamt = 6;
			else if(Fast) moveamt = 8;
			else moveamt = 12;

			switch(wtcap) {
			case UNENCUMBERED: break;
			case SLT_ENCUMBER: moveamt = (moveamt * 4) / 3; break;
			case MOD_ENCUMBER: moveamt *= 2; break;
			case HVY_ENCUMBER: moveamt *= 4; break;
			default: moveamt *= 12; break;
			}
			moverate += moveamt;
			settrack();
		    }

		    if(moverate > 0) {
			movemon();
			/* a monster may have levteleported player -dlc */
			if (u.utotype) deferred_goto();
			if(!rn2(u.uevent.udemigod ? 25 :
				(depth(&u.uz) >
				 depth(&stronghold_level))
				? 50 : 70))
			    (void) makemon((struct permonst *)0, 0, 0);
			++monstermoves;
			remove_cadavers(&fobj);
			remove_cadavers(&invent);
			moverate -= 12;
		    }
		    if(Glib) glibr();
		    nh_timeout();
		    ++moves;
		    if (u.ublesscnt)  u.ublesscnt--;
		    if(flags.time) flags.botl = 1;
		    /* One possible result of prayer is healing.  Whether or
		     * not you get healed depends on your current hit points.
		     * If you are allowed to regenerate during the prayer, the
		     * end-of-prayer calculation messes up on this.
		     */
		    if (u.uinvulnerable)
			;
		    else
#ifdef POLYSELF
		    if (u.mtimedone && u.mh < u.mhmax) {
			if (u.mh < 1) {
			    rehumanize();
			    moverate = 0;
			} else if (Regeneration ||
				 (wtcap < MOD_ENCUMBER && !(moves%20))) {
			    flags.botl = 1;
			    u.mh++;
			}
		    } else
#endif
		    if(u.uhp < u.uhpmax) {
			if(u.ulevel > 9) {
			    int heal;

			    if(HRegeneration ||
			       (!(moves%3) &&
				(wtcap < MOD_ENCUMBER || !flags.mv))) {
				flags.botl = 1;
				if (ACURR(A_CON) <= 12) heal = 1;
				else heal = rnd((int) ACURR(A_CON)-12);
				if (heal > u.ulevel-9) heal = u.ulevel-9;
				u.uhp += heal;
				if(u.uhp > u.uhpmax)
				    u.uhp = u.uhpmax;
			    }
			} else if(HRegeneration ||
				  ((wtcap < MOD_ENCUMBER || !flags.mv) &&
				   (!(moves%((MAXULEV+12)/(u.ulevel+2)+1))))) {
			    flags.botl = 1;
			    u.uhp++;
			}
		    }

		    if (wtcap > MOD_ENCUMBER && flags.mv) {
			if(!(wtcap < EXT_ENCUMBER ? moves%30 : moves%10)) {
			    if(u.uhp > 1) {
				u.uhp--;
			    } else {
				pline("You pass out from exertion!");
				exercise(A_CON, FALSE);
				nomul(-10);
				u.usleep = 1;
			    }
			}
		    }

		    if ((u.uen < u.uenmax) &&
			((wtcap < MOD_ENCUMBER &&
			  (!(moves%((MAXULEV + 1 - u.ulevel) *
				    (pl_character[0] == 'W' ? 3 : 4) / 2))))
			 || Energy_regeneration)) {
			u.uen +=
			    rn1((int)(ACURR(A_WIS) + ACURR(A_INT)) / 10 + 1,1);
			if (u.uen > u.uenmax)  u.uen = u.uenmax;
			flags.botl = 1;
		    }

		    if(!u.uinvulnerable) {
			if(Teleportation && !rn2(85)) {
#ifdef REDO		    /* clear doagain keystrokes */
			    pushch(0);
			    savech(0);
#endif
			    tele();
			}
#ifdef POLYSELF
			if(Polymorph && !rn2(100)) {
			    if (multi >= 0) {
				if (occupation)
				    stop_occupation();
				else
				    nomul(0);
			    }
			    polyself();
			    moverate = 0;
			} else if (u.ulycn >= 0 && !rn2(80 - (20 * night()))) {
			    if (multi >= 0) {
				if (occupation)
				    stop_occupation();
				else
				    nomul(0);
			    }
			    you_were();
			    moverate = 0;
			}
#endif
		    }

		    if(Searching && multi >= 0) (void) dosearch0(1);
		    do_storms();
		    hatch_eggs();
		    burn_lamps();
		    gethungry();
		    exerchk();
		    invault();
		    amulet();
		    if (!rn2(40+(int)(ACURR(A_DEX)*3))) 
			u_wipe_engr(rnd(3));
		    if (u.uevent.udemigod && !u.uinvulnerable) {
			if (u.udg_cnt) u.udg_cnt--;
			if (!u.udg_cnt) {
			    intervene();
			    u.udg_cnt = rn1(200, 50);
			}
		    }
		    restore_attrib();
		    /* underwater and waterlevel vision are done here */
		    if (Is_waterlevel(&u.uz))
			movebubbles();
		    else if (Underwater)
			under_water(0);

#ifdef POLYSELF
		    if ((oldmtimedone && !u.mtimedone) ||
			(!oldmtimedone && u.mtimedone)) moverate = 0;
#endif
		}
		if(multi < 0) {
			if(!++multi){
				pline("%s",nomovemsg ? nomovemsg :
					(const char *)"You can move again.");
				nomovemsg = 0;
				u.usleep = 0;
				if(afternmv) (*afternmv)();
				afternmv = 0;
			}
		}

		find_ac();
		if(!flags.mv || Blind) {
		    /* redo monsters if hallu or wearing a helm of telepathy */
		    if (Hallucination ||
			(HTelepat & (WORN_HELMET|WORN_AMUL|W_ART)))
			see_monsters();

		    /* redo objects if hallucinating */
		    if (Hallucination) see_objects();

		    /* update swallowed display */
		    if (Hallucination && u.uswallow) swallowed(0);

		    if (vision_full_recalc) vision_recalc(0);	/* vision! */
		}
		if(flags.botl || flags.botlx) bot();

		flags.move = 1;

		if(multi >= 0 && occupation) {
#ifdef MICRO
			abort_lev = 0;
			if (kbhit()) {
				if ((ch = Getchar()) == ABORT)
					abort_lev++;
# ifdef REDO
				else
					pushch(ch);
# endif /* REDO */
			}
			if (!abort_lev && (*occupation)() == 0)
#else
			if ((*occupation)() == 0)
#endif
				occupation = 0;
			if(
#ifdef MICRO
			   abort_lev ||
#endif
			   monster_nearby()) {
				stop_occupation();
				reset_eat();
			}
#ifdef MICRO
			if (!(++occtime % 7))
				display_nhwindow(WIN_MAP, FALSE);
#endif
			continue;
		}

		if((u.uhave.amulet || Clairvoyant) && !In_endgame(&u.uz) &&
						!(moves%15) && !rn2(2))
			do_vicinity_map();

		if(u.utrap && u.utraptype == TT_LAVA) {
		    if(!is_lava(u.ux,u.uy))
			u.utrap = 0;
		    else {
			u.utrap -= 1<<8;
			if(u.utrap < 1<<8) {
			    killer_format = KILLED_BY;
			    killer = "molten lava";
			    You("sink below the surface and suffocate.");
			    done(DROWNING); /*whatever*/
			} else if(didmove && !u.umoved) {
			    Norep("You sink deeper into the lava.");
			    u.utrap += rnd(4);
			}
		    }
		}

		u.umoved = FALSE;
		if(!didmove || moverate <= 0) {
		    if(multi > 0) {
			lookaround();
			if(!multi) {	/* lookaround may clear multi */
				flags.move = 0;
				continue;
			}
			if(flags.mv) {
				if(multi < COLNO && !--multi)
					flags.mv = flags.run = 0;
				domove();
			} else {
				--multi;
				rhack(save_cm);
			}
		    } else if(multi == 0) {
#ifdef MAIL
			ckmailstatus();
#endif
			rhack(NULL);
		    }
		}
		if (vision_full_recalc) vision_recalc(0);	/* vision! */
		if(multi && multi%7 == 0)
			display_nhwindow(WIN_MAP, FALSE);
	}
}
Esempio n. 5
0
/* u.dx and u.dy must be set */
bool
attack(struct monst *mtmp)
{
	schar tmp;
	boolean malive = TRUE;
	struct permonst *mdat;

	mdat = mtmp->data;
	u_wipe_engr(3);   /* andrew@orca: prevent unlimited pick-axe attacks */

	if (mdat->mlet == 'L' && !mtmp->mfroz && !mtmp->msleep &&
	    !mtmp->mconf && mtmp->mcansee && !rn2(7) &&
	    (m_move(mtmp, 0) == 2 /* he died */ || /* he moved: */
	     mtmp->mx != u.ux + u.dx || mtmp->my != u.uy + u.dy))
		return (FALSE);

	if (mtmp->mimic) {
		if (!u.ustuck && !mtmp->mflee)
			u.ustuck = mtmp;
		switch (levl[u.ux + u.dx][u.uy + u.dy].scrsym) {
		case '+':
			pline("The door actually was a Mimic.");
			break;
		case '$':
			pline("The chest was a Mimic!");
			break;
		default:
			pline("Wait! That's a Mimic!");
		}
		wakeup(mtmp);	/* clears mtmp->mimic */
		return (TRUE);
	}

	wakeup(mtmp);

	if (mtmp->mhide && mtmp->mundetected) {
		struct obj *obj;

		mtmp->mundetected = 0;
		if ((obj = o_at(mtmp->mx, mtmp->my)) && !Blind)
			pline("Wait! There's a %s hiding under %s!",
			      mdat->mname, doname(obj));
		return (TRUE);
	}

	tmp = u.uluck + u.ulevel + mdat->ac + abon();
	if (uwep) {
		if (uwep->olet == WEAPON_SYM || uwep->otyp == PICK_AXE)
			tmp += uwep->spe;
		if (uwep->otyp == TWO_HANDED_SWORD)
			tmp -= 1;
		else if (uwep->otyp == DAGGER)
			tmp += 2;
		else if (uwep->otyp == CRYSKNIFE)
			tmp += 3;
		else if (uwep->otyp == SPEAR &&
			 strchr("XDne", mdat->mlet))
			tmp += 2;
	}
	if (mtmp->msleep) {
		mtmp->msleep = 0;
		tmp += 2;
	}
	if (mtmp->mfroz) {
		tmp += 4;
		if (!rn2(10))
			mtmp->mfroz = 0;
	}
	if (mtmp->mflee)
		tmp += 2;
	if (u.utrap)
		tmp -= 3;

	/* with a lot of luggage, your agility diminishes */
	tmp -= (inv_weight() + 40) / 20;

	if (tmp <= rnd(20) && !u.uswallow) {
		if (Blind)
			pline("You miss it.");
		else
			pline("You miss %s.", monnam(mtmp));
	} else {
		/* we hit the monster; be careful: it might die! */

		if ((malive = hmon(mtmp, uwep, 0)) == TRUE) {
			/* monster still alive */
			if (!rn2(25) && mtmp->mhp < mtmp->mhpmax / 2) {
				mtmp->mflee = 1;
				if (!rn2(3))
					mtmp->mfleetim = rnd(100);
				if (u.ustuck == mtmp && !u.uswallow)
					u.ustuck = 0;
			}
#ifndef NOWORM
			if (mtmp->wormno)
				cutworm(mtmp, u.ux + u.dx, u.uy + u.dy,
					uwep ? uwep->otyp : 0);
#endif /* NOWORM */
		}
		if (mdat->mlet == 'a') {
			if (rn2(2)) {
				pline("You are splashed by the blob's acid!");
				losehp_m(rnd(6), mtmp);
				if (!rn2(30))
					corrode_armor();
			}
			if (!rn2(6))
				corrode_weapon();
		}
	}
	if (malive && mdat->mlet == 'E' && canseemon(mtmp)
	    && !mtmp->mcan && rn2(3)) {
		if (mtmp->mcansee) {
			pline("You are frozen by the floating eye's gaze!");
			nomul((u.ulevel > 6 || rn2(4)) ? rn1(20, -21) : -200);
		} else {
			pline("The blinded floating eye cannot defend itself.");
			if (!rn2(500))
				if ((int)u.uluck > LUCKMIN)
					u.uluck--;
		}
	}
	return (TRUE);
}
Esempio n. 6
0
/* return 1 if action took 1 (or more) moves, 0 if error or aborted */
static int
doengrave_core(const struct nh_cmd_arg *arg, int auto_elbereth)
{
    boolean dengr = FALSE;      /* TRUE if we wipe out the current engraving */
    boolean doblind = FALSE;    /* TRUE if engraving blinds the player */
    boolean doknown = FALSE;    /* TRUE if we identify the stylus */
    boolean doknown_after = FALSE;      /* TRUE if we identify the stylus after
                                           successfully engraving. */
    boolean eow = FALSE;        /* TRUE if we are overwriting oep */
    boolean jello = FALSE;      /* TRUE if we are engraving in slime */
    boolean ptext = TRUE;       /* TRUE if we must prompt for engrave text */
    boolean teleengr = FALSE;   /* TRUE if we move the old engraving */
    boolean zapwand = FALSE;    /* TRUE if we remove a wand charge */
    xchar type = DUST;          /* Type of engraving made */
    const char *buf;            /* Buffer for final/poly engraving text */
    const char *ebuf;           /* Buffer for initial engraving text */
    const char *qbuf;           /* Buffer for query text */
    const char *post_engr_text; /* Text displayed after engraving prompt */
    const char *everb;          /* Present tense of engraving type */
    const char *eloc;           /* Where the engraving is (ie dust/floor/...) */
    const char *esp;            /* Iterator over ebuf; mostly handles spaces */
    char *sp;                   /* Ditto for mutable copies of ebuf */
    int len;                    /* # of nonspace chars of new engraving text */
    int maxelen;                /* Max allowable length of engraving text */
    int helpless_time;          /* Temporary for calculating helplessness */
    const char *helpless_endmsg;/* Temporary for helpless end message */
    struct engr *oep = engr_at(level, u.ux, u.uy);
    struct obj *otmp;
    int cramps = 0;             /* How much your hand is cramping up from writing */

    /* The current engraving */
    const char *writer;

    buf = "";
    ebuf = "";
    post_engr_text = "";
    maxelen = 255; /* same value as in 3.4.3 */

    if (is_demon(youmonst.data) || youmonst.data->mlet == S_VAMPIRE)
        type = ENGR_BLOOD;

    /* Can the adventurer engrave at all? */

    if (Engulfed) {
        if (is_animal(u.ustuck->data)) {
            pline("What would you write?  \"Jonah was here\"?");
            return 0;
        } else if (is_whirly(u.ustuck->data)) {
            pline("You can't reach the %s.", surface(u.ux, u.uy));
            return 0;
        } else
            jello = TRUE;
    } else if (is_lava(level, u.ux, u.uy)) {
        pline("You can't write on the lava!");
        return 0;
    } else if (Underwater) {
        pline("You can't write underwater!");
        return 0;
    } else if (is_pool(level, u.ux, u.uy) ||
               IS_FOUNTAIN(level->locations[u.ux][u.uy].typ)) {
        pline("You can't write on the water!");
        return 0;
    }
    if (Is_airlevel(&u.uz) || Is_waterlevel(&u.uz) /* in bubble */ ) {
        pline("You can't write in thin air!");
        return 0;
    } else if (u.utrap && u.utraptype == TT_INFLOOR) {
        pline ("You can't write on the %s while embedded therein.",
               surface(u.ux, u.uy));
        return 0;
    } else if (u.utrap && u.utraptype == TT_ICEBLOCK) {
        pline("You cannot write on the %s while embedded in a block of %s.",
              surface(u.ux,u.uy),
              (level->locations[u.ux][u.uy].typ == ICE) ? "it" : "ice");
        return 0;
    } else if (!accessible(level, u.ux, u.uy)) {
        /* stone, tree, wall, secret corridor, pool, lava, bars */
        pline("You can't write here.");
        return 0;
    }
    if (cantwield(youmonst.data)) {
        pline("You can't even hold anything!");
        return 0;
    }
    if (check_capacity(NULL))
        return 0;

    /* One may write with finger, or weapon, or wand, or..., or... Edited by
       GAN 10/20/86 so as not to change weapon wielded. */

    otmp = getargobj(arg, styluses, "write with");
    if (!otmp)
        return 0;       /* otmp == &zeroobj if fingers */

    if (otmp == &zeroobj)
        writer = makeplural(body_part(FINGER));
    else
        writer = xname(otmp);

    /* There's no reason you should be able to write with a wand while both
       your hands are tied up. */
    if (!freehand() && otmp != uwep && !otmp->owornmask) {
        pline("You have no free %s to write with!", body_part(HAND));
        return 0;
    }

    if (jello) {
        pline("You tickle %s with your %s.", mon_nam(u.ustuck), writer);
        pline("Your message dissolves...");
        return 0;
    }
    if (otmp->oclass != WAND_CLASS && !can_reach_floor()) {
        pline("You can't reach the %s!", surface(u.ux, u.uy));
        return 0;
    }
    if (IS_ALTAR(level->locations[u.ux][u.uy].typ)) {
        pline("You make a motion towards the altar with your %s.", writer);
        altar_wrath(u.ux, u.uy);
        return 0;
    }
    if (IS_GRAVE(level->locations[u.ux][u.uy].typ)) {
        if (otmp == &zeroobj) { /* using only finger */
            pline("You would only make a small smudge on the %s.",
                  surface(u.ux, u.uy));
            return 0;
        } else if (!level->locations[u.ux][u.uy].disturbed) {
            pline("You disturb the undead!");
            level->locations[u.ux][u.uy].disturbed = 1;
            makemon(&mons[PM_GHOUL], level, u.ux, u.uy, NO_MM_FLAGS);
            return 1;
        }
    }

    /* SPFX for items */

    switch (otmp->oclass) {
    default:
    case AMULET_CLASS:
    case CHAIN_CLASS:
    case POTION_CLASS:
    case COIN_CLASS:
        break;

    case RING_CLASS:
        /* "diamond" rings and others should work */
    case GEM_CLASS:
        /* diamonds & other hard gems should work */
        if (objects[otmp->otyp].oc_tough) {
            type = ENGRAVE;
            break;
        }
        break;

    case ARMOR_CLASS:
        if (is_boots(otmp)) {
            type = DUST;
            break;
        }
        /* fall through */
        /* Objects too large to engrave with */
    case BALL_CLASS:
    case ROCK_CLASS:
        pline("You can't engrave with such a large object!");
        ptext = FALSE;
        break;

        /* Objects too silly to engrave with */
    case FOOD_CLASS:
    case SCROLL_CLASS:
    case SPBOOK_CLASS:
        pline("Your %s would get %s.", xname(otmp),
              is_ice(level, u.ux, u.uy) ? "all frosty" : "too dirty");
        ptext = FALSE;
        break;

    case RANDOM_CLASS: /* This should mean fingers */
        break;

        /* The charge is removed from the wand before prompting for the
           engraving text, because all kinds of setup decisions and
           pre-engraving messages are based upon knowing what type of engraving 
           the wand is going to do.  Also, the player will have potentially
           seen "You wrest .." message, and therefore will know they are using
           a charge. */
    case WAND_CLASS:
        if (zappable(otmp)) {
            check_unpaid(otmp);
            zapwand = TRUE;
            if (Levitation)
                ptext = FALSE;

            switch (otmp->otyp) {
                /* DUST wands */
            default:
                break;

                /* NODIR wands */
            case WAN_LIGHT:
            case WAN_SECRET_DOOR_DETECTION:
            case WAN_CREATE_MONSTER:
            case WAN_WISHING:
            case WAN_ENLIGHTENMENT:
                zapnodir(otmp);
                break;

                /* IMMEDIATE wands */
                /* If wand is "IMMEDIATE", remember to affect the previous
                   engraving even if turning to dust. */
            case WAN_STRIKING:
                post_engr_text =
                    "The wand unsuccessfully fights your attempt to write!";
                doknown_after = TRUE;
                break;
            case WAN_SLOW_MONSTER:
                if (!Blind) {
                    post_engr_text = msgprintf("The bugs on the %s slow down!",
                                               surface(u.ux, u.uy));
                    doknown_after = TRUE;
                }
                break;
            case WAN_SPEED_MONSTER:
                if (!Blind) {
                    post_engr_text = msgprintf("The bugs on the %s speed up!",
                                               surface(u.ux, u.uy));
                    doknown_after = TRUE;
                }
                break;
            case WAN_POLYMORPH:
                if (oep) {
                    if (!Blind) {
                        type = (xchar) 0;       /* random */
                        buf = random_engraving(rng_main);
                        doknown = TRUE;
                    }
                    dengr = TRUE;
                }
                break;
            case WAN_NOTHING:
            case WAN_UNDEAD_TURNING:
            case WAN_OPENING:
            case WAN_LOCKING:
            case WAN_PROBING:
                break;

                /* RAY wands */
            case WAN_MAGIC_MISSILE:
                ptext = TRUE;
                if (!Blind) {
                    post_engr_text = msgprintf(
                        "The %s is riddled by bullet holes!",
                        surface(u.ux, u.uy));
                    doknown_after = TRUE;
                }
                break;

                /* can't tell sleep from death - Eric Backus */
            case WAN_SLEEP:
            case WAN_DEATH:
                if (!Blind) {
                    post_engr_text = msgprintf(
                        "The bugs on the %s stop moving!", surface(u.ux, u.uy));
                }
                break;

            case WAN_COLD:
                if (!Blind) {
                    post_engr_text = "A few ice cubes drop from the wand.";
                    doknown_after = TRUE;
                }
                if (!oep || (oep->engr_type != BURN))
                    break;
            case WAN_CANCELLATION:
            case WAN_MAKE_INVISIBLE:
                if (oep && oep->engr_type != HEADSTONE) {
                    if (!Blind)
                        pline("The engraving on the %s vanishes!",
                              surface(u.ux, u.uy));
                    dengr = TRUE;
                }
                break;
            case WAN_TELEPORTATION:
                if (oep && oep->engr_type != HEADSTONE) {
                    if (!Blind)
                        pline("The engraving on the %s vanishes!",
                              surface(u.ux, u.uy));
                    teleengr = TRUE;
                }
                break;

                /* type = ENGRAVE wands */
            case WAN_DIGGING:
                ptext = TRUE;
                type = ENGRAVE;
                if (!objects[otmp->otyp].oc_name_known) {
                    if (flags.verbose)
                        pline("This %s is a wand of digging!", xname(otmp));
                    doknown = TRUE;
                }
                if (!Blind) {
                    post_engr_text =
                        IS_GRAVE(level->locations[u.ux][u.uy].typ) ?
                        "Chips fly out from the headstone." :
                        is_ice(level, u.ux, u.uy) ?
                        "Ice chips fly up from the ice surface!" :
                        (level->locations[u.ux][u.uy].typ == DRAWBRIDGE_DOWN) ?
                        "Splinters fly up from the bridge." :
                        "Gravel flies up from the floor.";
                }
                else
                    post_engr_text = "You hear drilling!";
                break;

                /* type = BURN wands */
            case WAN_FIRE:
                ptext = TRUE;
                type = BURN;
                if (!objects[otmp->otyp].oc_name_known) {
                    if (flags.verbose)
                        pline("This %s is a wand of fire!", xname(otmp));
                    doknown = TRUE;
                }
                post_engr_text = Blind ?
                    "You feel the wand heat up." :
                    "Flames fly from the wand.";
                break;
            case WAN_LIGHTNING:
                ptext = TRUE;
                type = BURN;
                if (!objects[otmp->otyp].oc_name_known) {
                    if (flags.verbose)
                        pline("This %s is a wand of lightning!", xname(otmp));
                    doknown = TRUE;
                }
                if (!Blind) {
                    post_engr_text = "Lightning arcs from the wand.";
                    doblind = TRUE;
                } else
                    post_engr_text = "You hear crackling!";
                break;
            
                /* type = MARK wands */
                /* type = ENGR_BLOOD wands */
            }
        } else /* end if zappable */ if (!can_reach_floor()) {
                pline("You can't reach the %s!", surface(u.ux, u.uy));
                /* If it's a wrestable wand, the player wasted a turn trying. */
                if (wrestable(otmp))
                    return 1;
                else
                    return 0;
            }
        break;
    
    case WEAPON_CLASS:
        if (is_blade(otmp)) {
            if ((int)otmp->spe > -3)
                type = ENGRAVE;
            else
                pline("Your %s too dull for engraving.", aobjnam(otmp, "are"));
        }
        break;

    case TOOL_CLASS:
        if (otmp == ublindf) {
            pline("That is a bit difficult to engrave with, don't you think?");
            return 0;
        }
        switch (otmp->otyp) {
        case MAGIC_MARKER:
            if (otmp->spe <= 0)
                pline("Your marker has dried out.");
            else
                type = MARK;
            break;
        case TOWEL:
            /* Can't really engrave with a towel */
            ptext = FALSE;
            if (oep)
                if ((oep->engr_type == DUST) || (oep->engr_type == ENGR_BLOOD)
                    || (oep->engr_type == MARK)) {
                    if (!Blind)
                        pline("You wipe out the message here.");
                    else
                        pline("Your %s %s %s.", xname(otmp),
                              otense(otmp, "get"),
                              is_ice(level, u.ux, u.uy) ? "frosty" : "dusty");
                    dengr = TRUE;
                } else
                    pline("Your %s can't wipe out this engraving.",
                          xname(otmp));
            else
                pline("Your %s %s %s.", xname(otmp), otense(otmp, "get"),
                      is_ice(level, u.ux, u.uy) ? "frosty" : "dusty");
            break;
        default:
            break;
        }
        break;

    case VENOM_CLASS:
    case ILLOBJ_CLASS:
        impossible("You're engraving with an illegal object!");
        break;
    }

    if (IS_GRAVE(level->locations[u.ux][u.uy].typ)) {
        if (type == ENGRAVE || type == 0)
            type = HEADSTONE;
        else {
            /* ensures the "cannot wipe out" case */
            type = DUST;
            dengr = FALSE;
            teleengr = FALSE;
            buf = "";
        }
    }

    /* End of implement setup */

    /* If engraving with wand, blow up the wand if cursed+unskilled */
    if (zapwand && !getwandlevel(&youmonst, otmp)) {
        backfire(otmp);
        exercise(A_STR, FALSE);
        return 1;
    }

    /* Identify stylus */
    if (doknown) {
        makeknown(otmp->otyp);
        more_experienced(0, 10);
    }

    if (teleengr) {
        rloc_engr(oep);
        oep = NULL;
    }

    if (dengr) {
        del_engr(oep, level);
        oep = NULL;
    }

    /* Something has changed the engraving here */
    if (*buf) {
        make_engr_at(level, u.ux, u.uy, buf, moves, type);
        pline("The engraving now reads: \"%s\".", buf);
        ptext = FALSE;
    }

    if (zapwand && (otmp->spe < 0)) {
        pline("%s %sturns to dust.", The(xname(otmp)),
              Blind ? "" : "glows violently, then ");
        if (!IS_GRAVE(level->locations[u.ux][u.uy].typ))
            pline("You are not going to get anywhere trying to write in the "
                  "%s with your dust.",
                  is_ice(level, u.ux, u.uy) ? "frost" : "dust");
        useup(otmp);
        ptext = FALSE;
    }

    if (!ptext) {       /* Early exit for some implements. */
        if (otmp->oclass == WAND_CLASS && !can_reach_floor())
            pline("You can't reach the %s!", surface(u.ux, u.uy));
        return 1;
    }

    /* Special effects should have deleted the current engraving (if possible)
       by now. */

    if (oep) {
        char c = 'n';

        /* Give player the choice to add to engraving. */

        if (type == HEADSTONE) {
            /* no choice, only append */
            c = 'y';
        } else if ((type == oep->engr_type) &&
                   (!Blind || (oep->engr_type == BURN) ||
                    (oep->engr_type == ENGR_LIGHTS) ||
                    (oep->engr_type == ENGRAVE))) {
            if (auto_elbereth)
                c = 'y';
            else
                c = yn_function("Do you want to add to the current engraving?",
                                ynqchars, 'y');
            if (c == 'q') {
                pline("Never mind.");
                return 0;
            }
        }

        if (c == 'n' || Blind) {

            if ((oep->engr_type == DUST) || (oep->engr_type == ENGR_BLOOD) ||
                (oep->engr_type == MARK)) {
                if (!Blind) {
                    pline("You wipe out the message that was %s here.",
                          ((oep->engr_type == DUST) ? "written in the dust" :
                           ((oep->engr_type == ENGR_BLOOD) ?
                            "scrawled in blood" : "written")));
                    del_engr(oep, level);
                    oep = NULL;
                } else
                    /* Don't delete engr until after we *know* we're engraving
                       */
                    eow = TRUE;
            } else if ((type == DUST) || (type == MARK) ||
                       (type == ENGR_BLOOD)) {
                pline("You cannot wipe out the message that is %s the %s here.",
                      oep->engr_type == BURN ? (is_ice(level, u.ux, u.uy) ?
                                                "melted into" : "burned into") :
                      "engraved in",
                      surface(u.ux, u.uy));
                return 1;
            } else if (oep->engr_type == ENGR_LIGHTS) {
                if (type == BURN) {
                    pline("The colored lights short out and go dark.");
                    eow = TRUE;
                } else {
                    pline("The colored lights distract you, and nothing "
                          "really gets written.");
                    return 1;
                }
            } else if ((type != oep->engr_type) || (c == 'n')) {
                if (!Blind || can_reach_floor())
                    pline("You will overwrite the current message.");
                eow = TRUE;
            }
        }
    }

    eloc = surface(u.ux, u.uy);
    switch (type) {
    default:
        everb = (oep &&
                 !eow ? "add to the weird writing on" : "write strangely on");
        break;
    case DUST:
        everb = (oep && !eow ? "add to the writing in" : "write in");
        eloc = is_ice(level, u.ux, u.uy) ? "frost" : "dust";
        break;
    case HEADSTONE:
        everb = (oep && !eow ? "add to the epitaph on" : "engrave on");
        break;
    case ENGRAVE:
        everb = (oep && !eow ? "add to the engraving in" : "engrave in");
        break;
    case BURN:
        everb = (oep && !eow ? (is_ice(level, u.ux, u.uy) ?
                                "add to the text melted into" :
                                "add to the text burned into") :
                 (is_ice(level, u.ux, u.uy) ? "melt into" : "burn into"));
        break;
    case MARK:
        everb = (oep && !eow ? "add to the graffiti on" : "scribble on");
        break;
    case ENGR_BLOOD:
        everb = (oep && !eow ? "add to the scrawl on" : "scrawl on");
        break;
    case ENGR_LIGHTS:
        /* This probably can't actually happen. */
        everb = (oep && !eow ? "add to the writing in" : "write in");
        eloc  = (oep && !eow ? "the colored lights"    : "colored lights");
        break;
    }

    /* Tell adventurer what is going on */
    if (otmp != &zeroobj)
        pline("You %s the %s with %s.", everb, eloc, doname(otmp));
    else
        pline("You %s the %s with your %s.", everb, eloc,
              makeplural(body_part(FINGER)));

    /* Prompt for engraving! */
    qbuf = msgprintf("What do you want to %s the %s here?", everb, eloc);
    if (auto_elbereth)
        ebuf = "Elbereth";
    else
        ebuf = getarglin(arg, qbuf);

    /* Count the actual # of chars engraved not including spaces */
    len = strlen(ebuf);
    for (esp = ebuf; *esp; esp++)
        if (isspace(*esp))
            len -= 1;

    if (len == 0 || strchr(ebuf, '\033')) {
        if (zapwand) {
            if (!Blind)
                pline("%s, then %s.", Tobjnam(otmp, "glow"),
                      otense(otmp, "fade"));
            return 1;
        } else {
            pline("Never mind.");
            if (otmp && otmp->oclass == WAND_CLASS && wrestable(otmp))
                return 1;       /* disallow zero turn wrest */
            else
                return 0;
        }
    }

    /* A single `x' is the traditional signature of an illiterate person */
    if (len != 1 || (!strchr(ebuf, 'x') && !strchr(ebuf, 'X')))
        break_conduct(conduct_illiterate);

    /* Degrade any existing text: */
    u_wipe_engr(rnd(3));

    /* Mix up the new text we are engraving if surface or state of mind is
       unsound. Note: this won't add or remove any spaces. */
    char ebuf_copy[strlen(ebuf) + 1];
    strcpy(ebuf_copy, ebuf);
    for (sp = ebuf_copy; *sp; sp++) {
        if (isspace(*sp))
            continue;
        /* NetHack Fourk balance adjustment:  writing Elbereth a whole lot of
         * times makes it harder to continue writing anything successfully.  */
        if (!rn2((((type == DUST || type == ENGR_BLOOD)) ? 150
                  : (type == ENGRAVE) ? 350 : 1500)
                 * u.ulevel / (1 + u.uconduct[conduct_elbereth])) ||
            (Blind && !rn2(11)) || (Confusion && !rn2(7)) ||
            (Stunned && !rn2(4)) || (Hallucination && !rn2(2))) {
            *sp = ' ' + rnd(96 - 2);    /* ASCII '!' thru '~' (excludes ' ' and 
                                           DEL) */
            cramps++;
        }
    }
    if ((Blind || Confusion || Hallucination || Stunned) && (cramps > 0))
        pline("You have difficulty writing in your present condition.");
    else if (cramps > 6)
        pline("Your entire %s is cramping up.  You simply cannot write any more right now.", body_part(ARM));
    else if (cramps > 4)
        pline("Your %s is cramping up very severely.", body_part(HAND));
    else if (cramps > 2)
        pline("Your %s is really cramping up.", body_part(HAND));
    else if (cramps > 1)
        pline("Your %s is cramping up.", body_part(HAND));
    else if (cramps > 0)
        pline("Your writing %s is beginning to cramp.", body_part(HAND));

    /* Previous engraving is overwritten */
    if (eow) {
        del_engr(oep, level);
        oep = NULL;
    }

    /* Figure out how long it took to engrave, and if player has engraved too
       much. */
    helpless_time = len / 10;
    helpless_endmsg = NULL;
    switch (type) {
    default:
        helpless_endmsg = "You finish your weird engraving.";
        break;
    case DUST:
        helpless_endmsg = "You finish writing in the dust.";
        break;
    case HEADSTONE:
    case ENGRAVE:
        if ((otmp->oclass == WEAPON_CLASS) &&
            ((otmp->otyp != ATHAME) || otmp->cursed)) {
            helpless_time = len;
            maxelen = ((otmp->spe + 3) * 2) + 1;
            /* -2 = 3, -1 = 5, 0 = 7, +1 = 9, +2 = 11 Note: this does not allow 
               a +0 anything (except an athame) to engrave "Elbereth" all at
               once.  However, you could now engrave "Elb", then "ere", then
               "th". */
            if (otmp->quan > 1L)
                otmp = splitobj(otmp, 1L);
            pline("Your %s dull.", aobjnam(otmp, "get"));
            if (otmp->unpaid) {
                struct monst *shkp = shop_keeper(level, *u.ushops);

                if (shkp) {
                    pline("You damage it, you pay for it!");
                    bill_dummy_object(otmp);
                }
            }
            if (len > maxelen) {
                helpless_time = maxelen;
                otmp->spe = -3;
            } else if (len > 1)
                otmp->spe -= len >> 1;
            else
                otmp->spe -= 1; /* Prevent infinite engraving */
        } else if ((otmp->oclass == RING_CLASS) || (otmp->oclass == GEM_CLASS))
Esempio n. 7
0
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);
	}
    }
}
Esempio n. 8
0
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();
    }
}