Exemplo n.º 1
0
/*
 * 从 i 开始, 其父节点路径中每个节点的 priority 小于该节点父节点的 priority, 则 TODO
 */
static void
float_up_or_down(struct heap *heap, size_t i)
{
    if (!float_up(heap, i)) {
        float_down(heap, i);
    }
}
Exemplo n.º 2
0
void
ringoff(struct obj *obj)
{
long mask;
	mask = obj->owornmask & W_RING;
	setworn(NULL, obj->owornmask);
	if(!(u.uprops[PROP(obj->otyp)].p_flgs & mask))
		impossible("Strange... I didn't know you had that ring.");
	u.uprops[PROP(obj->otyp)].p_flgs &= ~mask;
	switch(obj->otyp) {
	case RIN_FIRE_RESISTANCE:
		/* Bad luck if the player is in hell... --jgm */
		if (!Fire_resistance && dlevel >= 30) {
			pline("The flames of Hell burn you to a crisp.");
			killer = "stupidity in hell";
			done("burned");
		}
		break;
	case RIN_LEVITATION:
		if(!Levitation) {	/* no longer floating */
			float_down();
		}
		break;
	case RIN_GAIN_STRENGTH:
		u.ustr -= obj->spe;
		u.ustrmax -= obj->spe;
		if(u.ustr > 118) u.ustr = 118;
		if(u.ustrmax > 118) u.ustrmax = 118;
		flags.botl = 1;
		break;
	case RIN_INCREASE_DAMAGE:
		u.udaminc -= obj->spe;
		break;
	}
}
Exemplo n.º 3
0
//能保证权限大小排序么?
void
heap_rebuild(struct heap *heap)
{
    size_t i;

    for (i = heap->n / 2; i >= 1; i--) {
        float_down(heap, i);
    }
}
Exemplo n.º 4
0
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();
}
Exemplo n.º 5
0
static int arti_invoke(struct obj *obj)
{
    const struct artifact *oart = get_artifact(obj);

    if (!oart || !oart->inv_prop) {
        if (obj->oclass == WAND_CLASS)
            return do_break_wand(obj);
        else if (obj->oclass == GEM_CLASS || obj->oclass == TOOL_CLASS)
            return dorub(obj);
	else if (obj->otyp == CRYSTAL_BALL)
	    use_crystal_ball(obj);
	else
	    pline("Nothing happens.");
	return 1;
    }

    if (oart->inv_prop > LAST_PROP) {
	/* It's a special power, not "just" a property */
	if (obj->age > moves) {
	    /* the artifact is tired :-) */
	    pline("You feel that %s %s ignoring you.",
		     the(xname(obj)), otense(obj, "are"));
	    /* and just got more so; patience is essential... */
	    obj->age += (long) dice(3,10);
	    return 1;
	}
	obj->age = moves + rnz(100);

	switch(oart->inv_prop) {
	case TAMING: {
	    struct obj pseudo;
	    boolean unused_known;

	    pseudo = zeroobj;	/* neither cursed nor blessed */
	    pseudo.otyp = SCR_TAMING;
	    seffects(&pseudo, &unused_known);
	    break;
	  }
	case HEALING: {
	    int healamt = (u.uhpmax + 1 - u.uhp) / 2;
	    long creamed = (long)u.ucreamed;

	    if (Upolyd) healamt = (u.mhmax + 1 - u.mh) / 2;
	    if (healamt || Sick || Slimed || Blinded > creamed)
		pline("You feel better.");
	    else
		goto nothing_special;
	    if (healamt > 0) {
		if (Upolyd) u.mh += healamt;
		else u.uhp += healamt;
	    }
	    if (Sick) make_sick(0L,NULL,FALSE,SICK_ALL);
	    if (Slimed) Slimed = 0L;
	    if (Blinded > creamed) make_blinded(creamed, FALSE);
	    iflags.botl = 1;
	    break;
	  }
	case ENERGY_BOOST: {
	    int epboost = (u.uenmax + 1 - u.uen) / 2;
	    if (epboost > 120) epboost = 120;		/* arbitrary */
	    else if (epboost < 12) epboost = u.uenmax - u.uen;
	    if (epboost) {
		pline("You feel re-energized.");
		u.uen += epboost;
		iflags.botl = 1;
	    } else
		goto nothing_special;
	    break;
	  }
	case UNTRAP: {
	    if (!untrap(TRUE)) {
		obj->age = 0; /* don't charge for changing their mind */
		return 0;
	    }
	    break;
	  }
	case CHARGE_OBJ: {
	    struct obj *otmp = getobj(recharge_type, "charge");
	    boolean b_effect;

	    if (!otmp) {
		obj->age = 0;
		return 0;
	    }
	    b_effect = obj->blessed &&
		(Role_switch == oart->role || !oart->role);
	    recharge(otmp, b_effect ? 1 : obj->cursed ? -1 : 0);
	    update_inventory();
	    break;
	  }
	case LEV_TELE:
	    level_tele();
	    break;
	case CREATE_PORTAL: {
	    int i, num_ok_dungeons, last_ok_dungeon = 0;
	    d_level newlev;
	    extern int n_dgns; /* from dungeon.c */
	    struct nh_menuitem *items;
	    items = malloc(n_dgns * sizeof(struct nh_menuitem));

	    num_ok_dungeons = 0;
	    for (i = 0; i < n_dgns; i++) {
		if (!dungeons[i].dunlev_ureached)
		    continue;
		items[num_ok_dungeons].id = i+1;
		items[num_ok_dungeons].accel = 0;
		items[num_ok_dungeons].role = MI_NORMAL;
		items[num_ok_dungeons].selected = FALSE;
		strcpy(items[num_ok_dungeons].caption, dungeons[i].dname);
		num_ok_dungeons++;
		last_ok_dungeon = i;
	    }

	    if (num_ok_dungeons > 1) {
		/* more than one entry; display menu for choices */
		int n;
		int selected[1];

		n = display_menu(items, num_ok_dungeons, "Open a portal to which dungeon?", PICK_ONE, selected);
		free(items);
		if (n <= 0)
		    goto nothing_special;
		
		i = selected[0] - 1;
	    } else {
		free(items);
		i = last_ok_dungeon;	/* also first & only OK dungeon */
	    }

	    /*
	     * i is now index into dungeon structure for the new dungeon.
	     * Find the closest level in the given dungeon, open
	     * a use-once portal to that dungeon and go there.
	     * The closest level is either the entry or dunlev_ureached.
	     */
	    newlev.dnum = i;
	    if (dungeons[i].depth_start >= depth(&u.uz))
		newlev.dlevel = dungeons[i].entry_lev;
	    else
		newlev.dlevel = dungeons[i].dunlev_ureached;
	    if (u.uhave.amulet || In_endgame(&u.uz) || In_endgame(&newlev) ||
	       newlev.dnum == u.uz.dnum) {
		pline("You feel very disoriented for a moment.");
	    } else {
		if (!Blind) pline("You are surrounded by a shimmering sphere!");
		else pline("You feel weightless for a moment.");
		goto_level(&newlev, FALSE, FALSE, FALSE);
	    }
	    break;
	  }
	case ENLIGHTENING:
	    enlightenment(0);
	    break;
	case CREATE_AMMO: {
	    struct obj *otmp = mksobj(level, ARROW, TRUE, FALSE);

	    if (!otmp) goto nothing_special;
	    otmp->blessed = obj->blessed;
	    otmp->cursed = obj->cursed;
	    otmp->bknown = obj->bknown;
	    if (obj->blessed) {
		if (otmp->spe < 0) otmp->spe = 0;
		otmp->quan += rnd(10);
	    } else if (obj->cursed) {
		if (otmp->spe > 0) otmp->spe = 0;
	    } else
		otmp->quan += rnd(5);
	    otmp->owt = weight(otmp);
	    hold_another_object(otmp, "Suddenly %s out.", aobjnam(otmp, "fall"), NULL);
	    break;
	  }
	}
    } else {
	long eprop = (u.uprops[oart->inv_prop].extrinsic ^= W_ARTI),
	     iprop = u.uprops[oart->inv_prop].intrinsic;
	boolean on = (eprop & W_ARTI) != 0; /* true if invoked prop just set */

	if (on && obj->age > moves) {
	    /* the artifact is tired :-) */
	    u.uprops[oart->inv_prop].extrinsic ^= W_ARTI;
	    pline("You feel that %s %s ignoring you.",
		     the(xname(obj)), otense(obj, "are"));
	    /* can't just keep repeatedly trying */
	    obj->age += (long) dice(3,10);
	    return 1;
	} else if (!on) {
	    /* when turning off property, determine downtime */
	    /* arbitrary for now until we can tune this -dlc */
	    obj->age = moves + rnz(100);
	}

	if ((eprop & ~W_ARTI) || iprop) {
nothing_special:
	    /* you had the property from some other source too */
	    if (carried(obj))
		pline("You feel a surge of power, but nothing seems to happen.");
	    return 1;
	}
	switch(oart->inv_prop) {
	case CONFLICT:
	    if (on) pline("You feel like a rabble-rouser.");
	    else pline("You feel the tension decrease around you.");
	    break;
	case LEVITATION:
	    if (on) {
		float_up();
		spoteffects(FALSE);
	    } else float_down(I_SPECIAL|TIMEOUT, W_ARTI);
	    break;
	case INVIS:
	    if (BInvis || Blind) goto nothing_special;
	    newsym(u.ux, u.uy);
	    if (on)
		pline("Your body takes on a %s transparency...",
		     Hallucination ? "normal" : "strange");
	    else
		pline("Your body seems to unfade...");
	    break;
	}
    }

    return 1;
}
Exemplo n.º 6
0
/* Stop riding the current steed */
void
dismount_steed(int reason)
{
    struct monst *mtmp;
    struct obj *otmp;
    coord cc;
    const char *verb = "fall";
    boolean repair_leg_damage = TRUE;
    unsigned save_utrap = u.utrap;
    boolean have_spot = landing_spot(&cc, reason, 0);

    mtmp = u.usteed;    /* make a copy of steed pointer */
    /* Sanity check */
    if (!mtmp)  /* Just return silently */
        return;

    /* Check the reason for dismounting */
    otmp = which_armor(mtmp, os_saddle);
    switch (reason) {
    case DISMOUNT_THROWN:
        verb = "are thrown";
    case DISMOUNT_FELL:
        pline("You %s off of %s!", verb, mon_nam(mtmp));
        if (!have_spot)
            have_spot = landing_spot(&cc, reason, 1);
        losehp(rn1(10, 10), "killed in a riding accident");
        set_wounded_legs(LEFT_SIDE, (int)LWounded_legs + rn1(5, 5));
        set_wounded_legs(RIGHT_SIDE, (int)RWounded_legs + rn1(5, 5));
        repair_leg_damage = FALSE;
        break;
    case DISMOUNT_POLY:
        pline("You can no longer ride %s.", mon_nam(u.usteed));
        if (!have_spot)
            have_spot = landing_spot(&cc, reason, 1);
        break;
    case DISMOUNT_ENGULFED:
        /* caller displays message */
        break;
    case DISMOUNT_BONES:
        /* hero has just died... */
        break;
    case DISMOUNT_GENERIC:
        /* no messages, just make it so */
        break;
    case DISMOUNT_BYCHOICE:
    default:
        if (otmp && otmp->cursed) {
            pline("You can't.  The saddle %s cursed.",
                  otmp->bknown ? "is" : "seems to be");
            otmp->bknown = TRUE;
            return;
        }
        if (!have_spot) {
            pline("You can't. There isn't anywhere for you to stand.");
            return;
        }
        if (!mtmp->mnamelth) {
            pline("You've been through the dungeon on %s with no name.",
                  an(mtmp->data->mname));
            if (Hallucination)
                pline("It felt good to get out of the rain.");
        } else
            pline("You dismount %s.", mon_nam(mtmp));
    }
    /* While riding these refer to the steed's legs so after dismounting they
       refer to the player's legs once again. */
    if (repair_leg_damage)
        LWounded_legs = RWounded_legs = 0;

    /* Release the steed and saddle */
    u.usteed = 0;
    u.ugallop = 0L;

    /* Set player and steed's position.  Try moving the player first unless
       we're in the midst of creating a bones file. */
    if (reason == DISMOUNT_BONES) {
        /* move the steed to an adjacent square */
        if (enexto(&cc, level, u.ux, u.uy, mtmp->data))
            rloc_to(mtmp, cc.x, cc.y);
        else    /* evidently no room nearby; move steed elsewhere */
            rloc(mtmp, FALSE);
        return;
    }
    if (!DEADMONSTER(mtmp)) {
        place_monster(mtmp, u.ux, u.uy);
        if (!Engulfed && !u.ustuck && have_spot) {
            const struct permonst *mdat = mtmp->data;

            /* The steed may drop into water/lava */
            if (!is_flyer(mdat) && !is_floater(mdat) && !is_clinger(mdat)) {
                if (is_pool(level, u.ux, u.uy)) {
                    if (!Underwater)
                        pline("%s falls into the %s!", Monnam(mtmp),
                              surface(u.ux, u.uy));
                    if (!is_swimmer(mdat) && !amphibious(mdat)) {
                        killed(mtmp);
                        adjalign(-1);
                    }
                } else if (is_lava(level, u.ux, u.uy)) {
                    pline("%s is pulled into the lava!", Monnam(mtmp));
                    if (!likes_lava(mdat)) {
                        killed(mtmp);
                        adjalign(-1);
                    }
                }
            }
            /* Steed dismounting consists of two steps: being moved to another
               square, and descending to the floor.  We have functions to do
               each of these activities, but they're normally called
               individually and include an attempt to look at or pick up the
               objects on the floor: teleds() --> spoteffects() --> pickup()
               float_down() --> pickup() We use this kludge to make sure there
               is only one such attempt. Clearly this is not the best way to do
               it.  A full fix would involve having these functions not call
               pickup() at all, instead calling them first and calling pickup()
               afterwards.  But it would take a lot of work to keep this change
               from having any unforseen side effects (for instance, you would
               no longer be able to walk onto a square with a hole, and
               autopickup before falling into the hole). */
            /* [ALI] No need to move the player if the steed died. */
            if (!DEADMONSTER(mtmp)) {
                /* Keep steed here, move the player to cc; teleds() clears
                   u.utrap */
                in_steed_dismounting = TRUE;
                teleds(cc.x, cc.y, TRUE);
                in_steed_dismounting = FALSE;

                /* Put your steed in your trap */
                if (save_utrap)
                    mintrap(mtmp);
            }
            /* Couldn't... try placing the steed */
        } else if (enexto(&cc, level, u.ux, u.uy, mtmp->data)) {
            /* Keep player here, move the steed to cc */
            rloc_to(mtmp, cc.x, cc.y);
            /* Player stays put */
            /* Otherwise, kill the steed */
        } else {
            killed(mtmp);
            adjalign(-1);
        }
    }

    /* Return the player to the floor */
    if (reason != DISMOUNT_ENGULFED) {
        in_steed_dismounting = TRUE;
        float_down(0L);
        in_steed_dismounting = FALSE;
        encumber_msg();
        turnstate.vision_full_recalc = TRUE;
    } else
        /* polearms behave differently when not mounted */
        if (uwep && is_pole(uwep))
            u.bashmsg = FALSE;
    return;
}