Beispiel #1
0
static void e_died(struct entity *etmp, int dest, int how)
{
	if (is_u(etmp)) {
		if (how == DROWNING) {
			killer = 0;	/* drown() sets its own killer */
			drown();
		} else if (how == BURNING) {
			killer = 0;	/* lava_effects() sets its own killer */
			lava_effects();
		} else {
			coord xy;

			/* use more specific killer if specified */
			if (!killer) {
			    killer_format = KILLED_BY_AN;
			    killer = "falling drawbridge";
			}
			done(how);
			/* So, you didn't die */
			if (!e_survives_at(etmp, etmp->ex, etmp->ey)) {
			    if (enexto(&xy, level, etmp->ex, etmp->ey, etmp->edata)) {
				pline("A %s force teleports you away...",
				      Hallucination ? "normal" : "strange");
				teleds(xy.x, xy.y, FALSE);
			    }
			    /* otherwise on top of the drawbridge is the
			     * only viable spot in the dungeon, so stay there
			     */
			}
		}
		/* we might have crawled out of the moat to survive */
		etmp->ex = u.ux,  etmp->ey = u.uy;
	} else {
		int entitycnt;

		killer = 0;
		/* fake "digested to death" damage-type suppresses corpse */
#define mk_message(dest) ((dest & 1) ? "" : NULL)
#define mk_corpse(dest)  ((dest & 2) ? AD_DGST : AD_PHYS)
		/* if monsters are moving, one of them caused the destruction */
		if (flags.mon_moving)
		    monkilled(etmp->emon, mk_message(dest), mk_corpse(dest));
		else		/* you caused it */
		    xkilled(etmp->emon, dest);
		etmp->edata = NULL;

		/* dead long worm handling */
		for (entitycnt = 0; entitycnt < ENTITIES; entitycnt++) {
		    if (etmp != &(occupants[entitycnt]) &&
			etmp->emon == occupants[entitycnt].emon)
			occupants[entitycnt].edata = NULL;
		}
#undef mk_message
#undef mk_corpse
	}
}
int
tele_impl(boolean wizard_tele, boolean run_next_to_u)
{
    coord cc;

    /* Disable teleportation in stronghold && Vlad's Tower */
    if (level->flags.noteleport) {
        if (!wizard_tele) {
            pline("A mysterious force prevents you from teleporting!");
            return 1;
        }
    }

    /* don't show trap if "Sorry..." */
    if (!Blinded)
        make_blinded(0L, FALSE);

    /* when it happens at all, happens too often to be worth a custom RNG */
    if ((Uhave_amulet || On_W_tower_level(&u.uz)) && !rn2(3)) {
        pline("You feel disoriented for a moment.");
        return 1;
    }
    if ((Teleport_control && !Stunned) || wizard_tele) {
        if (u_helpless(hm_unconscious)) {
            pline("Being unconscious, you cannot control your teleport.");
        } else {
            pline("To what position do you%s want to be teleported?",
                  u.usteed ? msgcat(" and ", mon_nam(u.usteed)) : "");
            cc.x = u.ux;
            cc.y = u.uy;
            if (getpos(&cc, FALSE, "the desired position", FALSE)
                == NHCR_CLIENT_CANCEL)
                return 0; /* abort */

            if (run_next_to_u) {
                if (!next_to_u()) {
                    pline("You shudder for a moment.");
                    return 1;
                }
            }

            /* possible extensions: introduce a small error if magic power is
               low; allow transfer to solid rock */
            if (u_teleok(cc.x, cc.y, FALSE, wizard_tele)) {
                teleds(cc.x, cc.y, FALSE);
                return 1;
            }
            pline("Sorry...");
        }
    }

    safe_teleds(FALSE);
    return 1;
}
Beispiel #3
0
static void vault_tele(void)
{
	struct mkroom *croom = search_special(level, VAULT);
	coord c;

	if (croom && somexy(level, croom, &c) && teleok(c.x,c.y,FALSE)) {
		teleds(c.x,c.y,FALSE);
		return;
	}
	tele();
}
Beispiel #4
0
void tele_finish(Short x, Short y, Boolean controlled)
{
  Short nux,nuy;
  Boolean done = false;

  if (controlled) {
    if (teleok(x, y)) {
      teleds(x, y);
      done = true; //return;
    }
    message("Sorry ...");
  }
  if (!done) {
    do {
      nux = rnd(DCOLS-1);
      nuy = rund(DROWS);
    } while (!teleok(nux, nuy));
    teleds(nux, nuy);
  }
  // clean up after drowning victims
  if (map_mode_teleport == TELE_DROWN) {
    if (get_cell_type(floor_info[(Short) you.ux][(Short) you.uy]) == POOL)
      drown_finish();
    // else, after surviving, do we tick or not?  XXXX think about this.
  }
  // else, if scroll or command, tick; if random timer, don't tick.
  // wait hm.
  // random timer - never tick.
  // command - tick iff controlled
  // scroll - tick iff controlled
  // drown - ???
  // trap - ???
  else if (controlled && map_mode_teleport != TELE_RNDTIMER) {
    extern Boolean took_time;
    void end_turn_start_turn(); // in main.c
    took_time = true;
    end_turn_start_turn(); // XXXX
  }
  // finally, reset.
  map_mode_teleport = TELE_MAP;
}
Beispiel #5
0
boolean safe_teleds(boolean allow_drag)
{
	int nux, nuy, tcnt = 0;

	do {
		nux = rnd(COLNO-1);
		nuy = rn2(ROWNO);
	} while (!teleok(nux, nuy, (boolean)(tcnt > 200)) && ++tcnt <= 400);

	if (tcnt <= 400) {
		teleds(nux, nuy, allow_drag);
		return TRUE;
	} else
		return FALSE;
}
Beispiel #6
0
void
tele(void)
{
    coord cc;

    /* Disable teleportation in stronghold && Vlad's Tower */
    if (level->flags.noteleport) {
        if (!wizard) {
            pline("A mysterious force prevents you from teleporting!");
            return;
        }
    }

    /* don't show trap if "Sorry..." */
    if (!Blinded)
        make_blinded(0L, FALSE);

    if ((u.uhave.amulet || On_W_tower_level(&u.uz)) && !rn2(3)) {
        pline("You feel disoriented for a moment.");
        return;
    }
    if ((Teleport_control && !Stunned) || wizard) {
        if (unconscious()) {
            pline("Being unconscious, you cannot control your teleport.");
        } else {
            char buf[BUFSZ];

            if (u.usteed)
                sprintf(buf, " and %s", mon_nam(u.usteed));
            pline("To what position do you%s want to be teleported?",
                  u.usteed ? buf : "");
            cc.x = u.ux;
            cc.y = u.uy;
            if (getpos(&cc, TRUE, "the desired position") < 0)
                return; /* abort */
            /* possible extensions: introduce a small error if magic power is
               low; allow transfer to solid rock */
            if (teleok(cc.x, cc.y, FALSE)) {
                teleds(cc.x, cc.y, FALSE);
                return;
            }
            pline("Sorry...");
        }
    }

    safe_teleds(FALSE);
}
Beispiel #7
0
static void vtele()
{
  room_t *croom;
  extern room_t rooms[MAX_ROOMS]; // in make_level.c .... SIGH...
  for (croom = &rooms[0] ; croom->hx >= 0 ; croom++)
    if (croom->rtype == VAULT) {
      Short x,y;

      x = rund(2) ? croom->lx : croom->hx;
      y = rund(2) ? croom->ly : croom->hy;
      if (teleok(x,y)) {
	teleds(x,y);
	map_mode_teleport = TELE_MAP;
	return;
      }
    }
  tele();
}
Beispiel #8
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;
}
Beispiel #9
0
/* Start riding, with the given monster */
boolean
mount_steed(struct monst * mtmp,        /* The animal */
            boolean force)
{   /* Quietly force this animal */
    struct obj *otmp;
    const struct permonst *ptr;

    /* Sanity checks */
    if (u.usteed) {
        pline("You are already riding %s.", mon_nam(u.usteed));
        return FALSE;
    }

    /* Is the player in the right form? */
    if (Hallucination && !force) {
        pline("Maybe you should find a designated driver.");
        return FALSE;
    }
    /* While riding Wounded_legs refers to the steed's, not the hero's legs.
       That opens up a potential abuse where the player can mount a steed, then
       dismount immediately to heal leg damage, because leg damage is always
       healed upon dismount (Wounded_legs context switch). By preventing a hero
       with Wounded_legs from mounting a steed, the potential for abuse is
       minimized, if not eliminated altogether. */
    if (Wounded_legs) {
        pline("Your %s are in no shape for riding.",
              makeplural(body_part(LEG)));
        if (force && wizard && yn("Heal your legs?") == 'y')
            LWounded_legs = RWounded_legs = 0;
        else
            return FALSE;
    }

    if (Upolyd &&
            (!humanoid(youmonst.data) || verysmall(youmonst.data) ||
             bigmonst(youmonst.data) || slithy(youmonst.data))) {
        pline("You won't fit on a saddle.");
        return FALSE;
    }
    if (!force && (near_capacity() > SLT_ENCUMBER)) {
        pline("You can't do that while carrying so much stuff.");
        return FALSE;
    }

    /* Can the player reach and see the monster? */
    if (!mtmp ||
            (!force &&
             ((Blind && !Blind_telepat) || mtmp->mundetected ||
              mtmp->m_ap_type == M_AP_FURNITURE ||
              mtmp->m_ap_type == M_AP_OBJECT))) {
        pline("I see nobody there.");
        return FALSE;
    }

    struct test_move_cache cache;
    init_test_move_cache(&cache);

    if (Engulfed || u.ustuck || u.utrap || Punished ||
            !test_move(u.ux, u.uy, mtmp->mx - u.ux, mtmp->my - u.uy, 0,
                       TEST_MOVE, &cache)) {
        if (Punished || !(Engulfed || u.ustuck || u.utrap))
            pline("You are unable to swing your %s over.", body_part(LEG));
        else
            pline("You are stuck here for now.");
        return FALSE;
    }

    /* Is this a valid monster? */
    otmp = which_armor(mtmp, os_saddle);
    if (!otmp) {
        pline("%s is not saddled.", Monnam(mtmp));
        return FALSE;
    }
    ptr = mtmp->data;
    if (touch_petrifies(ptr) && !Stone_resistance) {
        pline("You touch %s.", mon_nam(mtmp));
        instapetrify(killer_msg(STONING,
                                msgcat("attempting to ride ", an(mtmp->data->mname))));
    }
    if (!mtmp->mtame || mtmp->isminion) {
        pline("I think %s would mind.", mon_nam(mtmp));
        return FALSE;
    }
    if (mtmp->mtrapped) {
        struct trap *t = t_at(level, mtmp->mx, mtmp->my);

        pline("You can't mount %s while %s's trapped in %s.", mon_nam(mtmp),
              mhe(mtmp), t ? an(trapexplain[t->ttyp - 1]) : "ice");
        return FALSE;
    }

    if (!force && !Role_if(PM_KNIGHT) && !(--mtmp->mtame)) {
        /* no longer tame */
        newsym(mtmp->mx, mtmp->my);
        pline("%s resists%s!", Monnam(mtmp),
              mtmp->mleashed ? " and its leash comes off" : "");
        if (mtmp->mleashed)
            m_unleash(mtmp, FALSE);
        return FALSE;
    }
    if (!force && Underwater && !is_swimmer(ptr)) {
        pline("You can't ride that creature while under water.");
        return FALSE;
    }
    if (!can_saddle(mtmp) || !can_ride(mtmp)) {
        pline("You can't ride such a creature.");
        return 0;
    }

    /* Is the player impaired? */
    if (!force && !is_floater(ptr) && !is_flyer(ptr) && Levitation &&
            !Lev_at_will) {
        pline("You cannot reach %s.", mon_nam(mtmp));
        return FALSE;
    }
    if (!force && uarm && is_metallic(uarm) && greatest_erosion(uarm)) {
        pline("Your %s armor is too stiff to be able to mount %s.",
              uarm->oeroded ? "rusty" : "corroded", mon_nam(mtmp));
        return FALSE;
    }
    if (!force &&
            (Confusion || Fumbling || Glib || Wounded_legs || otmp->cursed ||
             ((u.ulevel + mtmp->mtame < rnd(MAXULEV / 2 + 5)) &&
              (!Role_if(PM_KNIGHT))))) {
        if (Levitation) {
            pline("%s slips away from you.", Monnam(mtmp));
            return FALSE;
        }
        pline("You slip while trying to get on %s.", mon_nam(mtmp));

        const char *buf = msgcat(
                              "slipped while mounting ",
                              /* "a saddled mumak" or "a saddled pony called Dobbin" */
                              x_monnam(mtmp, ARTICLE_A, NULL,
                                       SUPPRESS_IT | SUPPRESS_INVISIBLE |
                                       SUPPRESS_HALLUCINATION, TRUE));
        losehp(rn1(5, 10), buf);
        return FALSE;
    }

    /* Success */
    maybewakesteed(mtmp);
    if (!force) {
        if (Levitation && !is_floater(ptr) && !is_flyer(ptr))
            /* Must have Lev_at_will at this point */
            pline("%s magically floats up!", Monnam(mtmp));
        pline("You mount %s.", mon_nam(mtmp));
    }
    /* setuwep handles polearms differently when you're mounted */
    if (uwep && is_pole(uwep))
        u.bashmsg = TRUE;
    u.usteed = mtmp;
    remove_monster(level, mtmp->mx, mtmp->my);
    teleds(mtmp->mx, mtmp->my, TRUE);
    return TRUE;
}