コード例 #1
0
void
runners(void)
{
    register struct linked_list *item;
    register struct thing *tp = NULL;

	for(item = mlist; item != NULL; item = next(item)) {
		tp = THINGPTR(item);
		turn_on(*tp, ISREADY);
	}

	for (;;) {
		
	for (item = mlist; item != NULL; item = next(item)) {
		tp = THINGPTR(item);

		if (on(*tp, ISREADY))
			break;
	}

	if (item == NULL)
		break;

	turn_off(*tp, ISREADY);

	if (on(*tp, ISHELD) && rnd(tp->t_stats.s_lvl) > 11) {
	    turn_off(*tp, ISHELD);
	    turn_on(*tp, ISRUN);
	    turn_off(*tp, ISDISGUISE);
	    tp->t_dest = &hero;
	    if (tp->t_stats.s_hpt < tp->maxstats.s_hpt)
		turn_on(*tp, ISFLEE);
	    if (cansee(tp->t_pos.y, tp->t_pos.x))
		msg("The %s breaks free from the hold spell!!!", 
			monsters[tp->t_index].m_name);
	}
	if (off(*tp, ISHELD) && on(*tp, ISRUN)) {
	    register int flee;

	    /* Should monster run away? */
	    flee = (on(*tp, ISFLEE) ||
		((tp->t_dest == &hero) && on(player, ISINWALL) &&
		 off(*tp, CANINWALL)));

	    if (off(*tp, ISSLOW) || tp->t_turn) {
		doctor(tp);
		do_chase(tp, flee);
	    }
	    if (off(*tp, ISDEAD) && on(*tp, ISHASTE)) {
		doctor(tp);
		do_chase(tp, flee);
	    }
	    if (off(*tp, ISDEAD)) {
		tp->t_turn ^= TRUE;
		tp->t_wasshot = FALSE;	/* Not shot anymore */
	    }
	}
    }
}
コード例 #2
0
void
chase_it(coord *runner, struct thing *th)
{
    struct linked_list  *item;
    struct thing    *tp;

    /* If we couldn't find him, something is funny */

    if ((item = find_mons(runner->y, runner->x)) == NULL)
    {
        debug("CHASER '%s'", unctrl(winat(runner->y, runner->x)));
        return;
    }

    tp = THINGPTR(item);

    /* Start the beastie running */

    tp->t_ischasing = TRUE;
    tp->t_chasee    = th;

    turn_on(*tp, ISRUN);
    turn_off(*tp, ISDISGUISE);

    return;
}
コード例 #3
0
void
listen(void)
{
    struct linked_list  *item;
    struct thing    *tp;
    int thief_bonus = -50;
    int mcount = 0;

    if (player.t_ctype == C_THIEF)
        thief_bonus = 10;

    for (item = mlist; item != NULL; item = next(item))
    {
        tp = THINGPTR(item);

        if (DISTANCE(hero, tp->t_pos) < 81
                && rnd(70) < (thief_bonus + 4 * pstats.s_dext +
                              6 * pstats.s_lvl))
        {
            msg("You hear a%s %s nearby.",
                vowelstr(monsters[tp->t_index].m_name),
                monsters[tp->t_index].m_name);
            mcount++;
        }
    }

    if (mcount == 0)
        msg("You hear nothing.");
}
コード例 #4
0
aggravate()
{
    register struct linked_list *mi;

    for (mi = mlist; mi != NULL; mi = next(mi))
	runto(THINGPTR(mi), &hero);
}
コード例 #5
0
void
aggravate(void)
{
    struct linked_list *mi;
    struct thing *tp;

    for (mi = mlist; mi != NULL; mi = next(mi))
    {
        tp = THINGPTR(mi);
        chase_it(&tp->t_pos, &player);
    }
}
コード例 #6
0
struct linked_list  *
find_mons(int y, int x)
{
    struct linked_list  *item;

    for (item = mlist; item != NULL; item = next(item))
    {
        struct thing *th = THINGPTR(item);

        if (th->t_pos.y == y && th->t_pos.x == x)
            return item;
    }
    return NULL;
}
コード例 #7
0
void
unsummon(fuse_arg *monny)
{
    struct linked_list *monst = monny->ll;
    struct linked_list  *sum_monst = (struct linked_list *) monst;
    struct thing    *tp = THINGPTR(sum_monst);
    char    *mname = monsters[tp->t_index].m_name;

    turn_off(*tp, WASSUMMONED);
    turn_off(player, HASSUMMONED);
    msg("Goodbye, master.");
    msg("The summoned %s phases out of existence", mname);
    killed(NULL, sum_monst, NOMESSAGE, NOPOINTS);
    mons_summoned--;
}
コード例 #8
0
void
electrificate(void)
{
    int affect_dist = 4 + player.t_stats.s_lvl / 4;
    struct linked_list  *item, *nitem;

    for (item = mlist; item != NULL; item = nitem)
    {
        struct thing *tp = THINGPTR(item);
        char *mname = monsters[tp->t_index].m_name;

        nitem = next(item);

        if (DISTANCE(tp->t_pos, hero) < affect_dist)
        {
            int damage = roll(2, player.t_stats.s_lvl);

            debug("Charge does %d (%d)", damage, tp->t_stats.s_hpt - damage);

            if (on(*tp, NOBOLT))
                continue;

            if ((tp->t_stats.s_hpt -= damage) <= 0)
            {
                msg("The %s is killed by an electric shock.", mname);
                killed(&player, item, NOMESSAGE, POINTS);
                continue;
            }

            if (rnd(tp->t_stats.s_intel / 5) == 0)
            {
                turn_on(*tp, ISFLEE);
                msg("The %s is shocked by electricity.", mname);
            }
            else
                msg("The %s is zapped by your electricity.", mname);

            summon_help(tp, NOFORCE);
            turn_off(*tp, ISFRIENDLY);
            turn_off(*tp, ISCHARMED);
            turn_on(*tp, ISRUN);
            turn_off(*tp, ISDISGUISE);
            chase_it(&tp->t_pos, &player);
            fighting = after = running = FALSE;
        }
    }
}
コード例 #9
0
coord   *
find_shoot(struct thing *tp, coord *dir)
{
    struct room *rtp;
    int ulx, uly, xmx, ymx, xmon, ymon, tpx, tpy, row, col;
    struct linked_list  *mon;
    struct thing    *ick;

    rtp = roomin(tp->t_pos);   /* Find room of chaser */

    if (rtp == NULL)
        return NULL;

    ulx = rtp->r_pos.x;
    uly = rtp->r_pos.y;
    xmx = rtp->r_max.x;
    ymx = rtp->r_max.y;

    tpx = tp->t_pos.x;
    tpy = tp->t_pos.y;

    for (col = ulx; col < (ulx + xmx); col++)
        for (row = uly; row < (uly + ymx); row++)
        {
            if (row > 0 && col > 0 && isalpha(mvwinch(mw, row, col)))
            {
		mon = find_mons(row, col);

                if (mon)
                {
                    ick = THINGPTR(mon);
                    xmon = ick->t_pos.x;
                    ymon = ick->t_pos.y;

                    if (!(good_monster(*ick)))
                    {
                        if (straight_shot(tpy, tpx, ymon, xmon, dir))
                            return(dir);
                    }
                }
            }
        }

    return(NULL);
}
コード例 #10
0
void
genocide(int flags)
{
    struct linked_list  *ip;
    struct thing    *mp;
    struct linked_list  *nip;
    int    which_monst;
    int    blessed = flags & ISBLESSED;
    int    cursed = flags & ISCURSED;

    while ((which_monst = get_monster_number("genocide")) == 0)
        ;

    if (cursed)    /* oops... */
    {
        new_level(THRONE, which_monst);
        msg("What's this I hear about you trying to wipe me out?");
        fighting = running = after = FALSE;
        return;
    }

    /* Remove this monster from the present level */

    for (ip = mlist; ip; ip = nip)
    {
        mp = THINGPTR(ip);
        nip = next(ip);

        if (mp->t_index == which_monst)
        {
            check_residue(mp);  /* Check for special features before removing */
            remove_monster(&mp->t_pos, ip);
        }
    }

    /* Remove from available monsters */

    monsters[which_monst].m_normal = FALSE;
    monsters[which_monst].m_wander = FALSE;
    mpos = 0;
    msg("You have wiped out the %s.", monsters[which_monst].m_name);

    if (blessed)
        genocide(ISNORMAL);
}
コード例 #11
0
/*
 * runners:
 *	Make all the running monsters move.
 */
runners()
{
	reg struct thing *tp;
	reg struct linked_list *mon,*nextmon;

	for (mon = mlist; mon != NULL; mon = nextmon) {
		tp = THINGPTR(mon);
		nextmon = next(mon);
		if (off(*tp, ISHELD) && on(*tp, ISRUN)) {
			if (tp->t_nomove > 0)
				if (--tp->t_nomove > 0)
					continue;
			if (on(*tp, ISHASTE))
				if (do_chase(mon) == -1)
					continue;
			if (off(*tp, ISSLOW) || tp->t_turn)
				if (do_chase(mon) == -1)
					continue;
			tp->t_turn ^= TRUE;
		}
	}
}
コード例 #12
0
struct linked_list  *
f_mons_a(int y, int x, int hit_bad)
{
    int row, col;
    struct linked_list  *item;
    struct thing    *tp;

    for (row = x - 1; row <= x + 1; row++)
        for (col = y - 1; col <= y + 1; col++)
            if (row == x && col == y)
                continue;
            else if (col > 0 && row > 0 &&
                isalpha(mvwinch(mw, col, row)) &&
                 ((item = find_mons(col, row)) != NULL))
            {
                tp = THINGPTR(item);
                if ((good_monster(*tp) && !hit_bad) ||
                    (!good_monster(*tp) && hit_bad))
                    return (item);
            }

    return (NULL);
}
コード例 #13
0
do_rooms()
{
    int i;
    struct room *rp;
    struct linked_list  *item;
    struct thing    *tp;
    int left_out;
    coord   top;
    coord   bsze;
    coord   mp;

    /*
     * bsze is the maximum room size
     */
    bsze.x = COLS / 3;
    bsze.y = (LINES - 2) / 3;

    /*
     * Clear things for a new level
     */
    for (rp = rooms; rp < &rooms[MAXROOMS]; rp++)
	rp->r_nexits = rp->r_flags = rp->r_fires = 0;

    /*
     * Put the gone rooms, if any, on the level
     */
    left_out = rnd(4);
    for (i = 0; i < left_out; i++)
	rooms[rnd_room()].r_flags |= ISGONE;

    /*
     * dig and populate all the rooms on the level
     */
    for (i = 0, rp = rooms; i < MAXROOMS; rp++, i++) {
	bool    has_gold = FALSE;

	/*
	 * Find upper left corner of box that this room goes in
	 */
	top.x = (i % 3) * bsze.x;
	top.y = i / 3 * bsze.y + 1;
	if (rp->r_flags & ISGONE) {

	    /*
	     * Place a gone room.  Make certain that there is a
	     * blank line for passage drawing.
	     */
	    do {
		rp->r_pos.x = top.x + rnd(bsze.x - 2) + 1;
		rp->r_pos.y = top.y + rnd(bsze.y - 2) + 1;
		rp->r_max.x = -COLS;
		rp->r_max.x = -LINES;
	    } while (rp->r_pos.y < 1 || rp->r_pos.y > LINES - 3);
	    continue;
	}
	if (rnd(80) < level - 15)
	    rp->r_flags |= ISDARK;

	/*
	 * Find a place and size for a random room
	 */
	do {
	    rp->r_max.x = rnd(bsze.x - 4) + 4;
	    rp->r_max.y = rnd(bsze.y - 4) + 4;
	    rp->r_pos.x = top.x + rnd(bsze.x - rp->r_max.x);
	    rp->r_pos.y = top.y + rnd(bsze.y - rp->r_max.y);
	} while (rp->r_pos.y == 0);

	/* Draw the room */
	draw_room(rp);

	/*
	 * Put the gold in
	 */
	if (rnd(100) < 50 && (!has_artifact || level >= max_level)) {
	    struct linked_list  *item;
	    struct object   *cur;
	    coord   tp;

	    has_gold = TRUE;    /* This room has gold in it */

	    item = spec_item(GOLD, NULL, NULL, NULL);
	    cur = OBJPTR(item);

	    /* Put it somewhere */
	    rnd_pos(rp, &tp);
	    cur->o_pos = tp;
	    /* Put the gold into the level list of items */
	    add_obj(item, tp.y, tp.x);

	    if (roomin(&tp) != rp) {
		endwin();
		abort();
	    }
	}

	/*
	 * Put the monster in
	 */
	if (rnd(100) < (has_gold ? 80 : 40)) {
	    short   which;
	    int i, count;

	    item = new_item(sizeof *tp);
	    tp = THINGPTR(item);
	    do {
		rnd_pos(rp, &mp);
	    } while (mvwinch(stdscr, mp.y, mp.x) != FLOOR);

	    which = randmonster(NOWANDER, NOGRAB);
	    new_monster(item, which, &mp, NOMAXSTATS);

	    /*
	     * See if we want to give it a treasure to carry
	     * around.
	     */
	    if (rnd(100) < monsters[tp->t_index].m_carry)
		attach(tp->t_pack, new_thing());

	    /*
	     * If it has a fire, mark it
	     */
	    if (on(*tp, HASFIRE)) {
		rp->r_flags |= HASFIRE;
		rp->r_fires++;
	    }

	    /*
	     * If it carries gold, give it some
	     */
	    if (on(*tp, CARRYGOLD)) {
		struct object   *cur;

		item = spec_item(GOLD, NULL, NULL, NULL);
		cur = OBJPTR(item);
		cur->o_count = GOLDCALC + GOLDCALC + GOLDCALC;
		cur->o_pos = tp->t_pos;
		attach(tp->t_pack, item);
	    }

	    i = rnd(7);
	    if (on(*tp, ISSWARM) && i < 5)
		count = roll(2, 4);
	    else if (on(*tp, ISFLOCK) && i < 5)
		count = roll(1, 4);
	    else
		count = 0;

	    for (i = 1; i <= count; i++) {
		coord   *mpos;

		if ((mpos = place_mons(mp.y, mp.x)) != NULL) {
		    struct linked_list  *nitem;

		    nitem = new_item(sizeof(struct thing));
		    new_monster(nitem, which, mpos,
			NOMAXSTATS);

		    /*
		     * If the monster is on a trap, trap
		     * it
		     */
		    if (isatrap(mvinch(mpos->y, mpos->x)))
			be_trapped(THINGPTR(nitem), mp);
		    if (on(*tp, ISFRIENDLY))
			turn_on(*(THINGPTR(nitem)),
			    ISFRIENDLY);
		    else
			turn_off(*(THINGPTR(nitem)),
			    ISFRIENDLY);
		}
	    }
	    if (count > 0) {
		int boost = rnd(3) + 1;

		if (on(*tp, LOWCAST) || on(*tp, MEDCAST) ||
		    on(*tp, HIGHCAST))
		    turn_on(*tp, CANCAST);
		tp->t_stats.s_hpt += 3 * boost;
		tp->t_stats.s_arm -= 2 * boost;
		tp->t_stats.s_lvl += 2 * boost;
		tp->t_stats.s_str += 2 * boost;
		tp->t_stats.s_intel += 2 * boost;
		tp->t_stats.s_exp += 4 * boost *
		    monsters[which].m_add_exp;
	    }
	}
    }
}
コード例 #14
0
struct linked_list *
wake_monster(int y, int x)
{
    struct thing    *tp;
    struct linked_list  *it;
    struct room *trp;
    char    *mname;

    if ((it = find_mons(y, x)) == NULL)
    {
        debug("Can't find monster in show.");
        return(NULL);
    }

    tp = THINGPTR(it);

    if ((good_monster(*tp)) || on(player, SUMMONING))
    {
        chase_it(&tp->t_pos, &player);
        turn_off(*tp, ISINVIS);
        turn_off(*tp, CANSURPRISE);
        return(it);
    }

    trp = roomin(tp->t_pos);   /* Current room for monster */
    mname = monsters[tp->t_index].m_name;

    /* Let greedy ones guard gold */

    if (on(*tp, ISGREED) && off(*tp, ISRUN))
        if ((trp != NULL) && (lvl_obj != NULL))
        {
            struct linked_list  *item;
            struct object   *cur;

            for (item = lvl_obj; item != NULL; item = next(item))
            {
                cur = OBJPTR(item);

                if ((cur->o_type == GOLD) &&
                    (roomin(cur->o_pos) == trp))
                {
                    /* Run to the gold */
                    tp->t_horde = cur;
                    turn_on(*tp, ISRUN);
                    turn_off(*tp, ISDISGUISE);
                    tp->t_ischasing = FALSE;
                    /* Make it worth protecting */
                    cur->o_count += roll(2, 3) * GOLDCALC;
                    break;
                }
            }
        }

    /*
     * Every time he sees mean monster, it might start chasing him unique
     * monsters always do
     */

    if (  (on(*tp, ISUNIQUE)) ||
          ( (rnd(100) > 33) &&
            on(*tp, ISMEAN) &&
            off(*tp, ISHELD) &&
            off(*tp, ISRUN) &&
            !is_stealth(&player) &&
            (off(player, ISINVIS) || on(*tp, CANSEE))
          )
       )
    {
        chase_it(&tp->t_pos, &player);
    }

    /* Handle gaze attacks */

    if (on(*tp, ISRUN) && cansee(tp->t_pos.y, tp->t_pos.x) &&
            off(player, ISINVIS))
    {
        if (on(*tp, CANHUH))    /* Confusion */
        {
            if (on(player, CANREFLECT))
            {
                msg("You reflect the bewildering stare of the %s.", mname);

                if (save_throw(VS_MAGIC, tp))
                {
                    msg("The %s is confused!", mname);
                    turn_on(*tp, ISHUH);
                }
                else
                    msg("The %s staggers for a moment.", mname);
            }
            else if (save(VS_MAGIC))
            {
                msg("You feel dizzy for a moment, but it quickly passes.");

                if (rnd(100) < 67)
                    turn_off(*tp, CANHUH);
            }
            else if (off(player, ISCLEAR))
            {
                if (off(player, ISHUH))
                {
                    light_fuse(FUSE_UNCONFUSE, 0, rnd(20) + HUHDURATION, AFTER);
                    msg("The %s's gaze has confused you.", mname);
                    turn_on(player, ISHUH);
                }
                else
                    lengthen_fuse(FUSE_UNCONFUSE, rnd(20) + HUHDURATION);
            }
        }

        if (on(*tp, CANSNORE))      /* Sleep */
        {
            if (on(player, CANREFLECT))
            {
                msg("You reflect the lethargic glance of the %s", mname);

                if (save_throw(VS_PARALYZATION, tp))
                {
                    msg("The %s falls asleep!", mname);
                    tp->t_no_move += SLEEPTIME;
                }
            }
            else if (no_command == 0 && !save(VS_PARALYZATION))
            {
                if (is_wearing(R_ALERT))
                    msg("You feel slightly drowsy for a moment.");
                else
                {
                    msg("The %s's gaze puts you to sleep.", mname);
                    no_command = SLEEPTIME;

                    if (rnd(100) < 50)
                        turn_off(*tp, CANSNORE);
                }
            }
        }

        if (on(*tp, CANFRIGHTEN))   /* Fear */
        {
            turn_off(*tp, CANFRIGHTEN);

            if (on(player, CANREFLECT))
            {
                msg("The %s sees its reflection. ", mname);

                if (save_throw(VS_MAGIC,tp))
                {
                    msg("The %s is terrified by its reflection!", mname);
                    turn_on(*tp, ISFLEE);
                }
            }
            else
            {
                if (!save(VS_WAND) && !(on(player, ISFLEE) &&
                       (player.t_chasee==tp)))
                {
                    if ((player.t_ctype != C_PALADIN) &&
                        off(player, SUPERHERO))
                    {
                        turn_on(player, ISFLEE);
                        player.t_ischasing = FALSE;
                        player.t_chasee    = tp;
                        msg("The sight of the %s terrifies you.", mname);
                    }
                    else
                        msg("My, the %s looks ugly.", mname);
                }
            }
        }

        if (on(*tp, LOOKSLOW))     /* Slow */
        {
            turn_off(*tp, LOOKSLOW);

            if (on(player, CANREFLECT))
            {
                msg("You reflect the mournful glare of the %s.", mname);

                if (save_throw(VS_MAGIC,tp))
                {
                    msg("The %s is slowing down!", mname);
                    turn_on(*tp, ISSLOW);
                }
            }
            else if (is_wearing(R_FREEDOM) || save(VS_MAGIC))
                msg("You feel run-down for a moment.");
            else
            {
                if (on(player, ISHASTE))    /* Already sped up */
                {
                    extinguish_fuse(FUSE_NOHASTE);
                    nohaste(NULL);
                }
                else
                {
                    msg("You feel yourself moving %sslower.",
                     on(player, ISSLOW) ? "even " : "");

                    if (on(player, ISSLOW))
                        lengthen_fuse(FUSE_NOSLOW, rnd(4) + 4);
                    else
                    {
                        turn_on(player, ISSLOW);
                        player.t_turn = TRUE;
                        light_fuse(FUSE_NOSLOW, 0, rnd(4) + 4, AFTER);
                    }
                }
            }
        }

        if (on(*tp, CANBLIND))  /* Blinding */
        {
            turn_off(*tp, CANBLIND);

            if (on(player, CANREFLECT))
            {
                msg("You reflect the blinding stare of the %s.", mname);

                if (save_throw(VS_WAND, tp))
                {
                    msg("The %s is blinded!", mname);
                    turn_on(*tp, ISHUH);
                }
            }
            else if (off(player, ISBLIND))
                if (save(VS_WAND) || is_wearing(R_TRUESEE) || is_wearing(R_SEEINVIS))
                    msg("Your eyes film over for a moment.");
                else
                {
                    msg("The gaze of the %s blinds you.", mname);
                    turn_on(player, ISBLIND);
                    light_fuse(FUSE_SIGHT, 0, rnd(30) + 20, AFTER);
                    look(FALSE);
                }
        }

        if (on(*tp, LOOKSTONE))  /* Stoning */
        {
            turn_off(*tp, LOOKSTONE);

            if (on(player, CANREFLECT))
            {
                msg("You reflect the flinty look of the %s.", mname);

                if (save_throw(VS_PETRIFICATION,tp))
                {
                    msg("The %s suddenly stiffens", mname);
                    tp->t_no_move += STONETIME;
                }
                else
                {
                    msg("The %s is turned to stone!", mname);
                    killed(&player, it, NOMESSAGE, POINTS);
                }
            }
            else
            {
                if (on(player, CANINWALL))
                    msg("The %s cannot focus on you.", mname);
                else
                {
                    msg("The gaze of the %s stiffens your limbs.", mname);

                    if (save(VS_PETRIFICATION))
                        no_command = STONETIME;
                    else if (rnd(100))
                        no_command = STONETIME * 3;
                    else
                    {
                        msg("The gaze of the %s petrifies you.", mname);
                        msg("You are turned to stone!!! --More--");
                        wait_for(' ');
                        death(D_PETRIFY);
                        return(it);
                    }
                }
            }
        }
    }

    /*
     * True Sight sees all Never see ISINWALL or CANSURPRISE See ISSHADOW
     * 80% See ISINVIS with See Invisibilty
     */

    if (off(player, CANTRUESEE) &&
        on(*tp, ISINWALL) || on(*tp, CANSURPRISE) ||
        (on(*tp, ISSHADOW) && rnd(100) < 80) ||
        (on(*tp, ISINVIS) && off(player, CANSEE)))
	{
	    /* 
	    TODO: incomplete - need to finish logic
	    int ch = mvwinch(stdscr, y, x); 
	    */
	}
	

    /* hero might be able to hear or smell monster if he can't see it */

    if ((rnd(player.t_ctype == C_THIEF ? 40 : 200) == 0 ||
            on(player, CANHEAR)) && !cansee(tp->t_pos.y, tp->t_pos.x))
        msg("You hear a %s nearby.", mname);
    else if ((rnd(player.t_ctype == C_THIEF ? 40 : 200) == 0 ||
            on(player, CANSCENT)) && !cansee(tp->t_pos.y, tp->t_pos.x))
        msg("You smell a %s nearby.", mname);

    return(it);
}
コード例 #15
0
void
wanderer(void)
{
    int i, cnt = 0;
    struct room *hr = roomin(hero);
    struct linked_list  *item;
    struct thing    *tp;
    coord   cp;
    char    *loc;
    int which;

    /* Find a place for it -- avoid the player's room */

    do
    {
        do
        {
            cnt++;
            i = rnd_room();
        }
        while (!(hr != &rooms[i] || levtype == MAZELEV
               || levtype == THRONE || cnt > 5000));

        rnd_pos(&rooms[i], &cp);
    }
    while(!step_ok(cp.y, cp.x, NOMONST, NULL));

    /* Create a new wandering monster */

    item = new_item(sizeof *tp);
    which = randmonster(TRUE, FALSE);
    new_monster(item, which, &cp, FALSE);

    tp = THINGPTR(item);
    tp->t_pos = cp;     /* Assign the position to the monster */

    chase_it(&tp->t_pos, &player);

    i = rnd(7);

    if (on(*tp, ISSWARM) && i < 5)
        cnt = roll(2, 4);
    else if (on(*tp, ISFLOCK) && i < 5)
        cnt = roll(1, 4);
    else
        cnt = 0;

    for (i = 1; i <= cnt; i++)
    {
        struct linked_list  *ip = creat_mons(tp, which, NOMESSAGE);

        if (ip != NULL)
        {
            struct thing    *mp = THINGPTR(ip);

            if (on(*tp, ISFRIENDLY))
                turn_on(*mp, ISFRIENDLY);
            else
                turn_off(*mp, ISFRIENDLY);
        }
    }

    if (cnt > 0)
    {
        if (on(*tp, LOWCAST) || on(*tp, MEDCAST) || on(*tp, HIGHCAST))
            turn_on(*tp, CANCAST);

        tp->t_stats.s_hpt += roll(2, 8);
        tp->t_stats.s_lvl += roll(2, 3);
        tp->t_stats.s_arm -= roll(1, 6);
        tp->t_stats.s_str += roll(2, 3);
        tp->t_stats.s_intel += roll(2, 3);
        tp->t_stats.s_exp += roll(2, 8) * monsters[which].m_add_exp;
    }

    i = DISTANCE(cp, hero);

    if (i < 20)
        loc = "very close to you";
    else if (i < 400)
        loc = "nearby";
    else
        loc = "in the distance";

    if (wizard)
        msg("Started a wandering %s.", monsters[tp->t_index].m_name);
    else if (on(*tp, ISUNDEAD) && (player.t_ctype == C_CLERIC ||
            player.t_ctype == C_PALADIN || is_wearing(R_PIETY)))
        msg("You sense a new ungodly monster %s.", loc);
    else if (on(player, CANHEAR) || (player.t_ctype == C_THIEF &&
            rnd(20) == 0))
        msg("You hear a new %s moving %s.",
            monsters[tp->t_index].m_name, loc);
    else if (on(player, CANSCENT) || (player.t_ctype == C_THIEF &&
            rnd(20) == 0))
        msg("You smell a new %s %s.", monsters[tp->t_index].m_name,
            loc);
}
コード例 #16
0
struct linked_list *
summon_monster(int type, int familiar, int print_message)
{
    struct linked_list  *mp;
    struct thing    *tp;
    int   monster;

    if (familiar && !is_wearing(R_WIZARD) && off(player, CANSUMMON))
    {
        msg("Only spellcasters can summon familiars!");
        return(NULL);
    }

    if (type == 0)    /* Random monster modified by level */
    {
        int ndice = min(pstats.s_lvl, (nummonst - NUMSUMMON) / 8);

        monster = min(nummonst, roll(ndice, pstats.s_charisma));
        
		/*
         * if a familiar exists, and it is higher in level, make it
         * again 
         */

        if (fam_ptr != NULL) 
		{
            struct thing   *fp = THINGPTR(fam_ptr);

            monster = max(fp->t_index, monster);
        }
	}
    else
        monster = type;

    turn_on(player, SUMMONING);

    mp = creat_mons(&player, monster, NOMESSAGE);

    if (!mp)
    {
        msg("Summon failed.");
        turn_off(player, SUMMONING);
        return(NULL);
    }

    if (print_message == MESSAGE)
    {
        msg("A %s appears out of nowhere!", monsters[monster].m_name);

        if (familiar)
            msg("I am here to serve %s.", whoami);
        else
        {
            msg("My goodness, are you Yendor?");
            ++mons_summoned;
            debug("%d monsters now summoned.", mons_summoned);
        }
    }

    tp = THINGPTR(mp);
    turn_on(*tp, ISCHARMED);    /* Summoned monsters are always charmed */

    if (familiar)
    {
        int i;
        static const unsigned long fam_on[]= {ISREGEN,CANSHOOT,CANWIELD,HASARMOR,ISFAMILIAR,0};
        static const unsigned long fam_off[]={ISMEAN, ISHUH, ISINVIS,
                    CANSURPRISE, NOMOVE,
                    ISSLOW, ISSHADOW, ISGREED, ISFAST,
                    CANFLY, ISFLEE, 0};

        for (i = 0; fam_on[i]; i++)
            turn_on(*tp, fam_on[i]);

        for (i = 0; fam_off[i]; i++)
            turn_off(*tp, fam_off[i]);

        if (fam_ptr != NULL)    /* Get rid of old familiar */
        {
            struct thing    *fp = THINGPTR(fam_ptr);
            struct linked_list  *fpack = fp->t_pack;
            struct linked_list  *item;

            if (fpack != NULL)  /* Transfer pack */
            {
                if (tp->t_pack == NULL)
                    tp->t_pack = fpack;
                else
                {
                    for(item=tp->t_pack; item->l_next != NULL; item=next(item))
                        ;   /* find last item in list */

                    item->l_next = fpack;
                    fpack->l_prev = item;
                }
            }

            fpack = NULL;
            killed(NULL, fam_ptr, NOMESSAGE, NOPOINTS);
        }

        fam_ptr = mp;
        fam_type = monster;

        /* improve their abilities a bit */

        tp->t_stats.s_hpt += roll(2, pstats.s_lvl);
        tp->t_stats.s_lvl += roll(2, (pstats.s_lvl / 4) + 1);
        tp->t_stats.s_arm -= roll(2, (pstats.s_lvl / 4) + 1);
        tp->t_stats.s_str += roll(2, (pstats.s_lvl / 4) + 1);
        tp->t_stats.s_intel += roll(2, (pstats.s_lvl / 4) + 1);
        tp->t_stats.s_wisdom += roll(2, (pstats.s_lvl / 4) + 1);
        tp->t_stats.s_dext += roll(2, (pstats.s_lvl / 4) + 1);
        tp->t_stats.s_const += roll(2, (pstats.s_lvl / 4) + 1);
        tp->t_stats.s_charisma += roll(2, (pstats.s_lvl / 4) + 1);
		
		/* some monsters do no damage by default */
		
		if (strcmp(tp->t_stats.s_dmg, "0d0") == 0)
            tp->t_stats.s_dmg = "1d8";
			
        tp->maxstats = tp->t_stats; /* structure assignment */
    }

    turn_off(player, SUMMONING);

    return(mp);
}
コード例 #17
0
void
new_monster(struct linked_list *item, int type, coord *cp, int max_monster)
{
    struct thing    *tp;
    struct monster  *mp;
    char    *ip, *hitp;
    int   i, min_intel, max_intel;
    int   num_dice, num_sides = 8, num_extra = 0;
    int eff_charisma = pstats.s_charisma;
    int eff_intel = pstats.s_intel;

    attach(mlist, item);
    tp = THINGPTR(item);
    tp->t_index = type;
    tp->t_wasshot = FALSE;
    tp->t_type = monsters[type].m_appear;
    tp->t_ctype = C_MONSTER;
    tp->t_no_move = 0;
    tp->t_doorgoal = -1;
    tp->t_pos = *cp;
    tp->t_oldpos = *cp;
    tp->t_oldch = CCHAR( mvwinch(cw, cp->y, cp->x) );
    mvwaddch(mw, cp->y, cp->x, tp->t_type);
    mp = &monsters[tp->t_index];

    /* Figure out monster's hit points */

    hitp = mp->m_stats.s_hpt;
    num_dice = atoi(hitp);

    if ((hitp = strchr(hitp, 'd')) != NULL)
    {
        num_sides = atoi(++hitp);

        if ((hitp = strchr(hitp, '+')) != NULL)
            num_extra = atoi(++hitp);
    }

    if (max_monster == MAXSTATS)
        tp->t_stats.s_hpt = num_dice * num_sides + num_extra;
    else
        tp->t_stats.s_hpt = roll(num_dice, num_sides) + num_extra;

    tp->t_stats.s_lvl = mp->m_stats.s_lvl;
    tp->t_stats.s_arm = mp->m_stats.s_arm;
    tp->t_stats.s_dmg = mp->m_stats.s_dmg;
    tp->t_stats.s_exp = mp->m_stats.s_exp + mp->m_add_exp * tp->t_stats.s_hpt;
    tp->t_stats.s_str = mp->m_stats.s_str;

    if (max_level > 30)
    {
        tp->t_stats.s_hpt += roll(4, (max_level - 60) * 2);
        tp->t_stats.s_lvl += roll(4, (max_level - 60) / 8);
        tp->t_stats.s_arm -= roll(2, (max_level - 60) / 8);
        tp->t_stats.s_str += roll(2, (max_level - 60) / 12);
        tp->t_stats.s_exp += roll(4, (max_level - 60) * 2) * mp->m_add_exp;
    }

    /*
     * just initailize others values to something reasonable for now
     * maybe someday will *really* put these in monster table
     */

    tp->t_stats.s_wisdom = 8 + rnd(4);
    tp->t_stats.s_dext = 8 + rnd(4);
    tp->t_stats.s_const = 8 + rnd(4);
    tp->t_stats.s_charisma = 8 + rnd(4);

    if (max_level > 45)
        tp->t_stats.s_dext += roll(2, (max_level - 50) / 8);

    /* Set the initial flags */

    for (i = 0; i < 16; i++)
        tp->t_flags[i] = 0;

    for (i = 0; i < 16; i++)
        turn_on(*tp, mp->m_flags[i]);

    /* suprising monsters don't always surprise you */

    if (!max_monster && on(*tp, CANSURPRISE) && rnd(100) < 20)
        turn_off(*tp, CANSURPRISE);

    /* If this monster is unique, genocide it */

    if (on(*tp, ISUNIQUE))
        mp->m_normal = FALSE;

    /* gods automatically get special abilities */

    if (on(*tp, ISGOD))
    {
        turn_on(*tp, CANFRIGHTEN);
        turn_on(*tp, CANCAST);
        turn_on(*tp, CANFLY);
        turn_on(*tp, CANBARGAIN);
        turn_on(*tp, ISLARGE);
        turn_on(*tp, CANTELEPORT);
        turn_on(*tp, CANSPEAK);
        turn_on(*tp, CANDARKEN);
        turn_on(*tp, CANSEE);
        turn_on(*tp, CANLIGHT);
        turn_on(*tp, BMAGICHIT);
    }

    tp->t_turn = TRUE;
    tp->t_pack = NULL;

    /* Figure intelligence */

    min_intel = atoi(mp->m_intel);

    if ((ip = (char *) strchr(mp->m_intel, '-')) == NULL)
        tp->t_stats.s_intel = min_intel;
    else
    {
        max_intel = atoi(++ip);

        if (max_monster)
            tp->t_stats.s_intel = max_intel;
        else
            tp->t_stats.s_intel = min_intel + rnd(max_intel - min_intel);
    }

    tp->t_stats.s_power = (rnd(tp->t_stats.s_lvl / 5) + 1) * tp->t_stats.s_intel;

    tp->maxstats = tp->t_stats; /* structure assignment */

    /* If the monster can shoot, it may have a weapon */

    if (on(*tp, CANSHOOT) && (max_monster || rnd(9) < 6))
    {
        struct linked_list  *thrower_item, *missile_item;
        struct object *thrower, *a_missile;

        thrower_item = new_item(sizeof *thrower);
        thrower = OBJPTR(thrower_item);
        carried_weapon(tp, thrower);

        missile_item = new_item(sizeof *a_missile);
        a_missile = OBJPTR(missile_item);
        carried_weapon(tp, a_missile);

        /* The monster may use a crossbow, sling, footbow, or an arrow */
        /* Take racial preferences into account */

        if ((strcmp(mp->m_name, "elf") == 0) ||
            (strcmp(mp->m_name, "noldor elf") == 0))
        {
            thrower->o_which = BOW;

            if (rnd(5) == 0)
                a_missile->o_which = SILVERARROW;
            else
                a_missile->o_which = ARROW;
        }
        else if ((strcmp(mp->m_name, "dwarf") == 0) ||
                (strcmp(mp->m_name, "kazad dwarf") == 0))
        {
            thrower->o_which = CROSSBOW;
            a_missile->o_which = BOLT;
        }
        else if (on(*tp, ISSMALL))
        {
            switch (rnd(3))
            {
                case 0:
                    thrower->o_which = SLING;
                    a_missile->o_which = BULLET;
                    break;
                default:
                    thrower->o_which = SLING;
                    a_missile->o_which = ROCK;
            }
        }
        else if (on(*tp, ISLARGE))
        {
            switch (rnd(4))
            {
                case 0:
                    thrower->o_which = CROSSBOW;
                    a_missile->o_which = BOLT;
                    break;

                case 1:
                    thrower->o_which = FOOTBOW;
                    a_missile->o_which = FBBOLT;
                    break;

                default:
                    thrower->o_which = BOW;

                    if (rnd(5) == 0)
                        a_missile->o_which = FLAMEARROW;
                    else
                        a_missile->o_which = ARROW;

                    break;
            }
        }
        else
        {
            switch (rnd(6))
            {
                case 1:
                    thrower->o_which = SLING;
                    a_missile->o_which = ROCK;
                    break;

                case 2:
                    thrower->o_which = CROSSBOW;
                    a_missile->o_which = BOLT;
                    break;

                case 3:
                    thrower->o_which = FOOTBOW;
                    a_missile->o_which = FBBOLT;
                    break;

                case 4:
                    thrower->o_which = BOW;
                    a_missile->o_which = ARROW;
                    break;

                default:
                    thrower->o_which = SLING;
                    a_missile->o_which = BULLET;
                    break;
            }
        }

        init_weapon(thrower, thrower->o_which);
        init_weapon(a_missile, a_missile->o_which);

        attach(tp->t_pack, thrower_item);
        attach(tp->t_pack, missile_item);
    }

    /* monsters that wield weapons */

    if (on(*tp, CANWIELD))
    {
        if (max_monster || rnd(3))
        {
            struct linked_list  *wield_item;
            struct object   *wielded;

            wield_item = new_item(sizeof *wielded);
            wielded = OBJPTR(wield_item);
            carried_weapon(tp, wielded);

            i = rnd(CLAYMORE - CLUB) + rnd(2 * tp->t_stats.s_lvl);
            i = min(i, CLAYMORE);
            wielded->o_which = i;
            init_weapon(wielded, wielded->o_which);

            /* Is it too heavy? */

            if (itemweight(wielded) > 8 * tp->t_stats.s_str)
                discard(wield_item);
            else
                attach(tp->t_pack, wield_item);
        }
    }

    if (is_wearing(R_AGGR))
        chase_it(cp, &player);
    else
    {
        turn_off(*tp, ISRUN);

        if (on(*tp, ISFLEE) && (rnd(4) == 0))
            turn_off(*tp, ISFLEE);

        if (rnd(luck) == 0)
            switch (player.t_ctype)
            {
                case C_MAGICIAN:
                case C_ILLUSION:
                    eff_intel = 2 * pstats.s_intel;
                    break;
                case C_DRUID:
                    eff_intel = 2 * pstats.s_intel;
                case C_RANGER:
                    eff_charisma = 2 * pstats.s_charisma;
                    break;
                case C_ASSASIN:
                case C_THIEF:
                case C_NINJA:
                    eff_charisma = pstats.s_charisma / 2;
                    break;
            }

        /* LOWFRIENDLY monsters might be friendly */

        i = roll(1,100);

        if (i == 0 || (on(*tp, LOWFRIENDLY) && i < eff_charisma) ||
            (on(*tp, MEDFRIENDLY) && i < 3 * eff_charisma) ||
            (on(*tp, HIGHFRIENDLY) && i < 5 * eff_charisma))
        {
            turn_on(*tp, ISFRIENDLY);
            turn_off(*tp, ISMEAN);
        }

        i = roll(1,100);

        if (i == 0 || (on(*tp, LOWCAST) && i < eff_intel) ||
            (on(*tp, MEDCAST) && i < 3 * eff_intel) ||
            (on(*tp, HIGHCAST) && i < 5 * eff_intel))
        {
            turn_on(*tp, CANCAST);
        }

        if (on(*tp, ISDISGUISE))
        {
            char    mch = 0;

            if (tp->t_pack != NULL)
                mch = (OBJPTR(tp->t_pack))->o_type;
            else
                switch (rnd(level > arts[0].ar_level ? 10 : 9))
                {
                    case 0: mch = GOLD;     break;
                    case 1: mch = POTION;   break;
                    case 2: mch = SCROLL;   break;
                    case 3: mch = FOOD;     break;
                    case 4: mch = WEAPON;   break;
                    case 5: mch = ARMOR;    break;
                    case 6: mch = RING;     break;
                    case 7: mch = STICK;    break;
                    case 8: mch = monsters[randmonster(NOWANDER, NOGRAB)].m_appear;
                                break;
                    case 9: mch = ARTIFACT; break;
                }

            tp->t_disguise = mch;
        }
    }
}
コード例 #18
0
ファイル: potions.c プロジェクト: ajpaulson/srogue11
/*
 * quaff:
 *	Let the hero drink a potion
 */
int quaff()
{
	struct object *obj;
	struct linked_list *item, *titem;
	struct thing *th;
	int wh;
	char buf[LINLEN];
	bool bless, curse;

	/*
	 * Make certain that it is somethings that we want to drink
	 */
	if ((item = get_item("quaff", POTION)) == NULL)
		return 0;
	obj = OBJPTR(item);
	if (obj->o_type != POTION) {
		msg("That's undrinkable!");
		after = FALSE;
		return 0;
	}
	wh = obj->o_which;
	bless = o_on(obj, ISBLESS);
	curse = o_on(obj, ISCURSED);
	del_pack(item);		/* get rid of it */

	/*
	 * Calculate the effect it has on the poor guy.
	 */
	switch(wh) {
	case P_CONFUSE:
		if (!bless) {
			if (pl_on(ISINVINC))
				msg("You remain level-headed.");
			else {
				chg_abil(WIS,-1,TRUE);		/* confuse his mind */
				if (pl_off(ISHUH)) {
					msg("Wait, what's going on here. Huh? What? Who?");
					if (pl_on(ISHUH))
						lengthen(unconfuse,rnd(8)+HUHDURATION);
					else
						fuse(unconfuse,TRUE,rnd(8)+HUHDURATION);
					player.t_flags |= ISHUH;
				}
			}
			p_know[P_CONFUSE] = TRUE;
		}
	when P_POISON:
		if (!bless) {
			if (pl_off(ISINVINC) && !iswearing(R_SUSTSTR) &&
			  !iswearing(R_SUSAB)) {
				chg_abil(CON,-1,TRUE);		
				chg_abil(STR,-(rnd(3)+1),TRUE);
				msg("You feel very sick now.");
			}
			else
				msg("You feel momentarily sick.");
			p_know[P_POISON] = TRUE;
		}
	when P_HEALING:
		if (!curse) {
			heal_self(4, TRUE);
			msg("You begin to feel better.");
			if (!iswearing(R_SLOW))
				notslow(FALSE);
			sight(FALSE);
			p_know[P_HEALING] = TRUE;
		}
	when P_STRENGTH:
		if (!curse) {
			msg("You feel stronger, now.  What bulging muscles!");
			chg_abil(STR,1,TRUE);
			p_know[P_STRENGTH] = TRUE;
		}
	when P_MFIND:
		/*
		 * Potion of monster detection - find all monsters
		 */
		if (mlist != NULL && !curse) {
			dispmons();
			mpos = 0;
			msg("You begin to sense the presence of monsters--More--");
			p_know[P_MFIND] = TRUE;
			wait_for(cw,' ');
			msg("");		/* clear line */
		}
		else
			msg("You have a strange feeling for a moment, then it passes.");
	when P_TFIND:
		/*
		 * Potion of magic detection.  Show the potions and scrolls
		 */
		if (lvl_obj != NULL && !curse) {
			struct linked_list *mobj;
			struct object *tp;
			bool show;

			show = FALSE;
			wclear(hw);
			for (mobj = lvl_obj; mobj != NULL; mobj = next(mobj)) {
				tp = OBJPTR(mobj);
				if (is_magic(tp)) {
					show = TRUE;
					mvwaddch(hw, tp->o_pos.y, tp->o_pos.x, MAGIC);
				}
			}
			for(titem = mlist; titem != NULL; titem = next(titem)) {
				struct linked_list *pitem;

				th = THINGPTR(titem);
				for(pitem=th->t_pack;pitem!=NULL;pitem=next(pitem)) {
					if (is_magic(ldata(pitem))) {
						show = TRUE;
						mvwaddch(hw,th->t_pos.y, th->t_pos.x, MAGIC);
					}
				}
			}
			if (show) {
				msg("You begin to sense the presence of magic.");
				overlay(hw,cw);
				p_know[P_TFIND] = TRUE;
				break;
			}
		}
		msg("You have a strange feeling for a moment, then it passes.");
	when P_PARALYZE:
		if (!bless) {
			if (pl_on(ISINVINC))
				msg("You feel numb for a moment.");
			else {
				msg("You can't move.");
				player.t_nocmd = HOLDTIME;
			}
			p_know[P_PARALYZE] = TRUE;
		}
	when P_SEEINVIS:
		if (!curse) {
			int invlen = roll(40,20);

			msg("This potion tastes like %s juice.", fruit);
			if (pl_off(CANSEE)) {
				player.t_flags |= CANSEE;
				fuse(unsee, TRUE, invlen);
				light(&hero);
			}
			else
				lengthen(unsee, invlen);
			sight(FALSE);
		}
	when P_RAISE:
		if (!curse) {
			msg("You suddenly feel much more skillful.");
			p_know[P_RAISE] = TRUE;
			chg_abil(DEX,1,TRUE);
			chg_abil(WIS,1,TRUE);
			chg_abil(CON,1,TRUE);
			raise_level();
		}
	when P_XHEAL:
		if (!curse) {
			heal_self(8, TRUE);
			if (rnd(100) < 50)
				chg_abil(CON,1,TRUE);
			msg("You begin to feel much better.");
			p_know[P_XHEAL] = TRUE;
			if (!iswearing(R_SLOW))
				notslow(FALSE);
			unconfuse();
			extinguish(unconfuse);
			sight(FALSE);
		}
	when P_HASTE:
		if (!curse) {
			add_haste(TRUE);
			msg("You feel yourself moving much faster.");
			p_know[P_HASTE] = TRUE;
		}
	when P_INVINC:
		if (!curse) {
			int time = rnd(400) + 350;

			msg("You feel invincible.");
			if (player.t_flags & ISINVINC)
				lengthen(notinvinc,time);
			else
				fuse(notinvinc,TRUE,time);
			player.t_flags |= ISINVINC;
			p_know[P_INVINC] = TRUE;
		}
	when P_SMART:
		if (!curse) {
			msg("You feel more perceptive.");
			p_know[P_SMART] = TRUE;
			chg_abil(WIS,1,TRUE);
		}
	when P_RESTORE:
		if (!curse) {
			msg("Hey, this tastes great. You feel warm all over.");
			him->s_re = max_stats.s_re;
			him->s_ef = max_stats.s_re;
			ringabil();				/* add in rings */
			updpack();				/* update weight */
			p_know[P_RESTORE] = TRUE;
			extinguish(rchg_str);	/* kill restore in from ulodyte */
		}
	when P_BLIND:
		if (!bless) {
			if (pl_on(ISINVINC))
				msg("The light dims for a moment.");
			else {
				chg_abil(WIS,-1,TRUE);
				msg("A cloak of darkness falls around you.");
				if (pl_off(ISBLIND)) {
					player.t_flags |= ISBLIND;
					fuse(sight, TRUE, rnd(400) + 450);
					light(&hero);
				}
			}
			p_know[P_BLIND] = TRUE;
		}
	when P_ETH:
		if (!curse) {
			int ethlen = roll(40,20);

			msg("You feel more vaporous.");
			if (pl_on(ISETHER))
				lengthen(noteth,ethlen);
			else
				fuse(noteth,TRUE,ethlen);
			player.t_flags |= ISETHER;
			p_know[P_ETH] = TRUE;
		}
	when P_NOP:
		msg("This potion tastes extremely dull.");
	when P_DEX:
		if (!curse) {
			chg_abil(DEX,1,TRUE);		/* increase dexterity */
			p_know[P_DEX] = TRUE;
			msg("You feel much more agile.");
		}
	when P_REGEN:
		if (!curse) {
			int reglen = rnd(450) + 450;

			if (pl_on(ISREGEN))
				lengthen(notregen, reglen);
			else
				fuse(notregen, TRUE, reglen);
			player.t_flags |= ISREGEN;
			msg("You feel yourself improved.");
			p_know[P_REGEN] = TRUE;
		}
	when P_DECREP:
	case P_SUPHERO: {
		int howmuch = rnd(3) + 1;

		if (wh == P_DECREP) {
			if (!bless) {
				if (iswearing(R_SUSAB) || pl_on(ISINVINC)) {
					msg("You feel momentarily woozy.");
					howmuch = 0;
				}
				else {
					msg("You feel crippled.");
					howmuch = -howmuch;
					if (!iswearing(R_SUSTSTR))
						chg_abil(STR,howmuch,TRUE);
				}
			}
			else
				howmuch = 0;
		}
		else {			/* potion of superhero */
			if (curse)
				howmuch = 0;
			msg("You feel invigorated.");
			chg_abil(STR,howmuch,TRUE);
		}
		chg_abil(CON,howmuch,TRUE);
		chg_abil(DEX,howmuch,TRUE);
		chg_abil(WIS,howmuch,TRUE);		/* change abilities */
		p_know[wh] = TRUE;
	}
	otherwise:
		msg("What an odd tasting potion!");
		return 0;
	}
	nochange = FALSE;
	if (p_know[wh] && p_guess[wh]) {
		free(p_guess[wh]);
		p_guess[wh] = NULL;
	}
	else if(!p_know[wh] && p_guess[wh] == NULL) {
		strcpy(buf, p_colors[wh]);
		msg(callit);
		if (get_str(buf, cw) == NORM) {
			p_guess[wh] = new(strlen(buf) + 1);
			strcpy(p_guess[wh], buf);
		}
コード例 #19
0
void
look(int wakeup)
{
    int     x, y;
    char   ch, och;
    int  oldx, oldy;
    int inpass, horizontal, vertical, do_light = FALSE, do_blank = FALSE;
    int passcount = 0;
    struct room *rp;
    int ey, ex;

    /* Are we moving vertically or horizontally? */

    if (runch == 'h' || runch == 'l')
        horizontal = TRUE;
    else
        horizontal = FALSE;

    if (runch == 'j' || runch == 'k')
        vertical = TRUE;
    else
        vertical = FALSE;

    getyx(cw, oldy, oldx);  /* Save current position */

    /*
     * Blank out the floor around our last position and check for moving
     * out of a corridor in a maze.
    */

    if (oldrp != NULL && (oldrp->r_flags & ISDARK) &&
            !(oldrp->r_flags & HASFIRE) && off(player, ISBLIND))
        do_blank = TRUE;

    for (x = player.t_oldpos.x - 1; x <= player.t_oldpos.x + 1; x++)
        for (y = player.t_oldpos.y - 1; y <= player.t_oldpos.y + 1;
                y++)
        {
            ch = show(y, x);

            if (do_blank && (y != hero.y || x != hero.x) && ch == FLOOR)
                mvwaddch(cw, y, x, ' ');

            /* Moving out of a corridor? */

            if (levtype == MAZELEV &&
                    (ch != '|' && ch != '-') && /* Not a wall */
                    ((vertical && x != player.t_oldpos.x &&
                      y == player.t_oldpos.y) ||
                     (horizontal && y != player.t_oldpos.y &&
                      x == player.t_oldpos.x)))
                do_light = TRUE;    /* Just came to a turn */
        }

    inpass = ((rp = roomin(hero)) == NULL);    /* Are we in a passage? */

    /* Are we coming out of a wall into a corridor in a maze? */
    och = show(player.t_oldpos.y, player.t_oldpos.x);
    ch = show(hero.y, hero.x);

    if (levtype == MAZELEV && (och == '|' || och == '-' ||
                               och == SECRETDOOR) && (ch != '|' && ch != '-' && ch != SECRETDOOR))
    {
        do_light = off(player, ISBLIND);    /* Light it up if not blind */
    }

    /* Look around the player */

    ey = hero.y + 1;
    ex = hero.x + 1;

    for (x = hero.x - 1; x <= ex; x++)
        if (x >= 0 && x < COLS)
            for (y = hero.y - 1; y <= ey; y++)
            {
                if (y <= 0 || y >= LINES - 2)
                    continue;

                if (isalpha(mvwinch(mw, y, x)))
                {
                    struct linked_list  *it;
                    struct thing    *tp;

                    if (wakeup)
                        it = wake_monster(y, x);
                    else
                        it = find_mons(y, x);

                    if (it == NULL)
                        continue;

                    tp = THINGPTR(it);
                    tp->t_oldch = CCHAR( mvinch(y, x) );

                    if (isatrap(tp->t_oldch))
                    {
                        struct trap *trp = trap_at(y, x);

                        tp->t_oldch = (trp->tr_flags & ISFOUND) ? tp->t_oldch
                                      : trp->tr_show;
                    }

                    if (tp->t_oldch == FLOOR &&
                            (rp->r_flags & ISDARK)
                            && !(rp->r_flags & HASFIRE) &&
                            off(player, ISBLIND))
                        tp->t_oldch = ' ';
                }

                /* Secret doors show as walls */

                if ((ch = show(y, x)) == SECRETDOOR)
                    ch = secretdoor(y, x);

                /*
                 * Don't show room walls if he is in a
                 * passage and check for maze turns
                */

                if (off(player, ISBLIND))
                {
                    if (y == hero.y && x == hero.x || (inpass && (ch == '-' ||
                                                       ch == '|')))
                        continue;

                    /* Are we at a crossroads in a maze? */

                    if (levtype == MAZELEV && (ch != '|' && ch != '-') &&
                            /* Not a wall */
                            ((vertical && x != hero.x && y == hero.y) ||
                             (horizontal && y != hero.y && x == hero.x)))
                        do_light = TRUE;
                    /* Just came to a turn */
                }
                else if (y != hero.y || x != hero.x)
                    continue;

                wmove(cw, y, x);
                waddch(cw, ch);

                if (door_stop && !firstmove && running)
                {
                    switch (runch)
                    {
                    case 'h':
                        if (x == ex)
                            continue;
                        break;
                    case 'j':
                        if (y == hero.y - 1)
                            continue;
                        break;
                    case 'k':
                        if (y == ey)
                            continue;
                        break;
                    case 'l':
                        if (x == hero.x - 1)
                            continue;
                        break;
                    case 'y':
                        if ((x + y) - (hero.x + hero.y) >= 1)
                            continue;
                        break;
                    case 'u':
                        if ((y - x) - (hero.y - hero.x) >= 1)
                            continue;
                        break;
                    case 'n':
                        if ((x + y) - (hero.x + hero.y) <= -1)
                            continue;
                        break;
                    case 'b':
                        if ((y - x) - (hero.y - hero.x) <= -1)
                            continue;
                        break;
                    }

                    switch (ch)
                    {
                    case DOOR:
                        if (x == hero.x || y == hero.y)
                            running = FALSE;
                        break;
                    case PASSAGE:
                        if (x == hero.x || y == hero.y)
                            passcount++;
                        break;
                    case FLOOR:

                        /*
                         * Stop by new passages in a
                         * maze (floor next to us)
                         */
                        if ((levtype == MAZELEV) &&
                                ((horizontal && x == hero.x && y != hero.y) ||
                                 (vertical &&   y == hero.y && x != hero.x)))
                            running = FALSE;

                    case '|':
                    case '-':
                    case ' ':
                        break;

                    default:
                        running = FALSE;
                        break;
                    }
                }
            }

    if (door_stop && !firstmove && passcount > 1)
        running = FALSE;

    /*
     * Do we have to light up the area (just stepped into a new
     * corridor)?
     */

    if (do_light && wakeup &&   /* wakeup will be true on a normal move */
            !(rp->r_flags & ISDARK) &&  /* We have some light */
            !ce(hero, player.t_oldpos)) /* Don't do anything if we didn't move */
        light(&hero);

    mvwaddch(cw, hero.y, hero.x, PLAYER);
    wmove(cw, oldy, oldx);

    if (wakeup)
    {
        player.t_oldpos = hero; /* Don't change if we didn't move */
        oldrp = rp;
    }
}
コード例 #20
0
void
teleport(void)
{
    struct room *new_rp = NULL, *old_rp = roomin(hero);

    int rm, which;
    coord c;
    int is_lit = FALSE; /* For saving room light state */
    int rand_position = TRUE;

    c = hero;

    mvwaddch(cw, hero.y, hero.x, mvwinch(stdscr, hero.y, hero.x));

    if (is_wearing(R_TELCONTROL))
    {
        msg("Where do you wish to teleport to? (* for help)");
        wmove(cw, hero.y, hero.x);
        wrefresh(cw);

        which = (short) (readchar() & 0177);

        while (which != (short) ESCAPE && which != (short) LINEFEED
            && which != (short) CARRIAGE_RETURN)
        {
            switch(which)
            {
                case 'h':   c.x--; break;
                case 'j':   c.y++; break;
                case 'k':   c.y--; break;
                case 'l':   c.x++; break;
                case 'y':   c.x--;
                            c.y--; break;
                case 'u':   c.x++;
                            c.y--; break;
                case 'b':   c.x--;
                            c.y++; break;
                case 'n':   c.x++;
                            c.y++; break;
                case '*':
                    msg("Use h,j,k,l,y,u,b,n to position cursor, then hit"
                        "return.");
            }

            c.y = max(c.y, 1);
            c.y = min(c.y, LINES - 3);
            c.x = max(c.x, 1);
            c.x = min(c.x, COLS - 1);
            wmove(cw, c.y, c.x);
            wrefresh(cw);
            which = (short) (readchar() & 0177);
        }

        which = winat(c.y, c.x);

        if ((which == FLOOR || which == PASSAGE || which == DOOR) &&
            ((ring_value(R_TELCONTROL) == 0 && rnd(10) < 6)
             || (ring_value(R_TELCONTROL) > 0 && rnd(10) < 9)))
        {
            rand_position = FALSE;
            msg("You attempt succeeds.");
            hero = c;
            new_rp = roomin(hero);
        }
        else
            msg("Your attempt fails.");
    }

    if (rand_position)
    {
        do
        {
            rm = rnd_room();
            rnd_pos(&rooms[rm], &hero);
        }
        while (winat(hero.y, hero.x) != FLOOR);

        new_rp = &rooms[rm];
    }

    /* If hero gets moved, darken old room */

    if (old_rp && old_rp != new_rp)
    {
        if (!(old_rp->r_flags & ISDARK))
            is_lit = TRUE;

        old_rp->r_flags |= ISDARK;  /* Fake darkness */
        light(&c);

        if (is_lit)
            old_rp->r_flags &= ~ISDARK; /* Restore light state */
    }

    light(&hero);
    mvwaddch(cw, hero.y, hero.x, PLAYER);

    /* turn off ISHELD in case teleportation was done while fighting */

    if (on(player, ISHELD))
    {
        struct linked_list  *ip, *nip;
        struct thing    *mp;

        turn_off(player, ISHELD);
        hold_count = 0;

        for (ip = mlist; ip; ip = nip)
        {
            mp = THINGPTR(ip);
            nip = next(ip);

            if (on(*mp, DIDHOLD))
            {
                turn_off(*mp, DIDHOLD);
                turn_on(*mp, CANHOLD);
            }

            turn_off(*mp, DIDSUFFOCATE);
        }
    }

    extinguish_fuse(FUSE_SUFFOCATE);
    player.t_no_move = 0;   /* not trapped anymore */
    count = 0;
    running = FALSE;

    return;
}
コード例 #21
0
ファイル: scrolls.c プロジェクト: ajpaulson/srogue11
/*
 * read_scroll:
 *	Let the hero read a scroll
 */
int read_scroll()
{
	struct object *obj;
	struct linked_list *item;
	int i, j, wh;
	unsigned long ch, nch;
	struct room *rp;
	struct linked_list *titem;
	char buf[LINLEN];
	bool bless, curse;

	if ((item = get_item("read", SCROLL)) == NULL)
		return 0;
	obj = OBJPTR(item);
	if (obj->o_type != SCROLL) {
		msg("Nothing to read.");
		after = FALSE;
		return 0;
	}
	msg("As you read the scroll, it vanishes.");
	wh = obj->o_which;
	bless = o_on(obj, ISBLESS);
	curse = o_on(obj, ISCURSED);
	del_pack(item);		/* Get rid of the thing */

	/*
	 * Calculate the effect it has on the hero
	 */
	switch(wh) {
	case S_KNOWALL:
		if (!curse) {
			idenpack();				/* identify all the pack */
			msg("You feel more knowledgable.");
			chg_abil(WIS,1,TRUE);
			s_know[S_KNOWALL] = TRUE;
		}
	when S_CONFUSE:
		if (!curse) {
			/*
			 * Scroll of monster confusion.  Give him that power.
			 */
			msg("Your hands begin to glow red.");
			player.t_flags |= CANHUH;
			s_know[S_CONFUSE] = TRUE;
		}
	when S_LIGHT:
		rp = player.t_room;
		if (!curse) {
			if (rp == NULL) {
				s_know[S_LIGHT] = TRUE;
				msg("The corridor glows and then fades.");
			}
			else {
				if (rf_on(rp,ISDARK)) {
					s_know[S_LIGHT] = TRUE;
					msg("The room is lit.");
					rp->r_flags &= ~ISDARK;
				}
				light(&hero);
				mvwaddch(cw, hero.y, hero.x, PLAYER);
			}
		}
	when S_ARMOR:
		if (!curse) {
			if (cur_armor != NULL && o_off(cur_armor,ISPROT)) {
				s_know[S_ARMOR] = TRUE;
				msg("Your armor glows faintly for a moment.");
				if (o_on(cur_armor,ISCURSED))
					cur_armor->o_ac = armors[cur_armor->o_which].a_class;
				else
					cur_armor->o_ac--;
				resoflg(cur_armor,ISCURSED);
			}
		}
	when S_HOLD:
		if (!curse) {
			/*
			 * Hold monster scroll.  Stop all monsters within 3 spaces
			 * from chasing after the hero.
			 */
			int x,y;
			struct linked_list *mon;

			for (x = hero.x - 3; x <= hero.x + 3; x++) {
				for (y = hero.y - 3; y <= hero.y + 3; y++) {
					if (y > 0 && x > 0 && isalpha(mvwinch(mw, y, x))) {
						if ((mon = find_mons(y, x)) != NULL) {
							struct thing *th;

							th = THINGPTR(mon);
							th->t_flags &= ~ISRUN;
							th->t_flags |= ISHELD;
							th->t_flags |= ISSTUCK;
						}
					}
				}
			}
		}
	when S_SLEEP:
		/*
		 * Scroll which makes you fall asleep
		 */
		if (!bless) {
			s_know[S_SLEEP] = TRUE;
			msg("You fall asleep.");
			player.t_nocmd += 4 + rnd(SLEEPTIME);
		}
	when S_CREATE:
		if (!bless) {
			if (makemons(mtlev[rnd(levcount)]->m_show))
				s_know[S_CREATE] = TRUE;
			else
				msg("You hear a faint cry of anguish in the distance.");
		}
	when S_IDENT:
		if (!curse) {
			msg("This scroll is an identify scroll");
			s_know[S_IDENT] = TRUE;
			whatis(NULL);
		}
	when S_MAP:
		if (curse)
			break;
		s_know[S_MAP] = TRUE;
		addmsg("Oh, now this scroll has a ");
		if (rnd(100) < 10 || bless) {
			addmsg("very detailed map on it.");
			endmsg();
			displevl();
		}
		else {
			addmsg("map on it.");
			endmsg();
			overwrite(stdscr, hw);
			for (i = 1; i < LINES - 2; i++) {
				for (j = 0; j < COLS; j++) {
					switch (nch = ch = mvwinch(hw, i, j)) {
						case SECRETDOOR:
							nch = DOOR;
							mvaddch(i, j, nch);
						case '-':
						case '|':
						case DOOR:
						case PASSAGE:
						case ' ':
						case STAIRS:
							if (mvwinch(mw, i, j) != ' ') {
								struct thing *it;
								struct linked_list *blah;

								blah = find_mons(i, j);
								if (blah != NULL) {
									it = THINGPTR(blah);
									if (it->t_oldch == ' ')
										it->t_oldch = nch;
								}
							}
							break;
						default:
							nch = ' ';
					}
					if (nch != ch)
						waddch(hw, nch);
				}
			}
			overlay(cw, hw);
			overwrite(hw, cw);
		}
	when S_GFIND:
		if (!curse) {
			int gtotal = 0;
			struct room *rp;

			wclear(hw);
			for (rp = rooms; rp < &rooms[MAXROOMS]; rp++) {
				gtotal += rp->r_goldval;
				if (rp->r_goldval != 0 &&
				  mvinch(rp->r_gold.y,rp->r_gold.x) == GOLD)
					mvwaddch(hw,rp->r_gold.y,rp->r_gold.x,GOLD);
			}
			if (gtotal) {
				s_know[S_GFIND] = TRUE;
				msg("You begin to feel greedy and sense gold.");
				overlay(hw,cw);
			}
			else
				msg("You begin to feel a pull downward.");
		}
	when S_TELEP:
		if (!curse) {
			int rm;
			struct room *cur_room;

			cur_room = player.t_room;
			rm = teleport(rndspot, &player);
			if (cur_room != &rooms[rm])
				s_know[S_TELEP] = TRUE;
		}
	when S_ENCH:
		if (!curse) {
			if (cur_weapon == NULL || (cur_weapon != NULL &&
			  (o_on(cur_weapon,ISPROT) || cur_weapon->o_type != WEAPON)))
				msg("You feel a strange sense of loss.");
			else {
				s_know[S_ENCH] = TRUE;
				if (o_on(cur_weapon,ISCURSED)) {
					resoflg(cur_weapon,ISCURSED);
					cur_weapon->o_hplus = rnd(2);
					cur_weapon->o_dplus = rnd(2);
				}
				else {		/* weapon was not cursed here */
					if (rnd(100) < 50)
						cur_weapon->o_hplus += 1;
					else
						cur_weapon->o_dplus += 1;
				}
				setoflg(cur_weapon, ISKNOW);
				msg("Your %s glows blue for a moment.",
				  w_magic[cur_weapon->o_which].mi_name);
			}
		}
	when S_SCARE:
		/*
		 * A monster will refuse to step on a scare monster scroll
		 * if it is dropped.  Thus reading it is a mistake and produces
		 * laughter at the poor rogue's boo boo.
		 */
		msg("You hear maniacal laughter in the distance.");
	when S_REMOVE:
		if (!curse) {
			if (cur_armor != NULL && o_off(cur_armor,ISPROT))
				resoflg(cur_armor,ISCURSED);
			if (cur_weapon != NULL && o_off(cur_weapon,ISPROT))
				resoflg(cur_weapon,ISCURSED);
			if (cur_ring[LEFT]!=NULL && o_off(cur_ring[LEFT],ISPROT))
				resoflg(cur_ring[LEFT],ISCURSED);
			if (cur_ring[RIGHT]!=NULL && o_off(cur_ring[RIGHT],ISPROT))
				resoflg(cur_ring[RIGHT],ISCURSED);
			msg("You feel as if somebody is watching over you.");
			s_know[S_REMOVE] = TRUE;
		}
	when S_AGGR:
		if (!bless) {
			if (mlist != NULL) {
				aggravate();
				msg("You hear a high pitched humming noise.");
				s_know[S_AGGR] = TRUE;
			}
		}
	when S_NOP:
		msg("This scroll seems to be blank.");
	when S_GENOCIDE:
		if (!curse) {
			msg("You have been granted the boon of genocide.");
			genocide();
			s_know[S_GENOCIDE] = TRUE;
		}
	when S_DCURSE:
		if (!bless) {
			struct linked_list *ll;
			struct object *lb;

			msg("Your pack shudders.");
			for (ll = pack ; ll != NULL ; ll = next(ll)) {
				lb = OBJPTR(ll);
				if (o_off(lb,ISPROT)) {
					resoflg(lb, ISBLESS);
					setoflg(lb, ISCURSED);
				}
			}
		}
	when S_DLEVEL:
		if (!bless) {
			int much = rnd(9) - 4;

			if (much != 0) {
				level += much;
				if (level < 1)
					level = 1;
				mpos = 0;
				new_level(NORMLEV);		/* change levels */
				msg("You are whisked away to another region.");
				s_know[S_DLEVEL] = TRUE;
			}
		}
	when S_PROTECT:
		if (!curse) {
			struct linked_list *ll;
			struct object *lb;

			msg("You are granted the power of protection.");
			if ((ll = get_item("protect",0)) != NULL) {
				lb = OBJPTR(ll);
				setoflg(lb,ISPROT);
				mpos = 0;
				msg("Protected %s.",inv_name(lb,TRUE));
			}
			s_know[S_PROTECT] = TRUE;
		}
	when S_ALLENCH:
		if (!curse) {
			struct linked_list *ll;
			struct object *lb;
			int howmuch, ac, good;

			msg("You are granted the power of enchantment.");
			good = TRUE;
			if ((ll = get_item("enchant",0)) != NULL) {
				lb = OBJPTR(ll);
				resoflg(lb,ISCURSED);
				resoflg(lb,ISPROT);
				howmuch = rnd(3) + 1;
				switch(lb->o_type) {
					case RING:
						if (lb->o_ac < 0)
							lb->o_ac = 0;
						lb->o_ac += howmuch;
					when ARMOR:
						ac = armors[lb->o_which].a_class;
						if (lb->o_ac > ac)
							lb->o_ac = ac;
						lb->o_ac -= howmuch;
					when STICK:
						lb->o_charges += howmuch + 10;
					when WEAPON:
						if (lb->o_dplus < 0)
							lb->o_dplus = 0;
						if (lb->o_hplus < 0)
							lb->o_hplus = 0;
						lb->o_hplus += howmuch;
						lb->o_dplus += howmuch;
					otherwise:
						msg("You are injured as the scroll flashes & bursts into flames !!!");
						chg_hpt(-roll(6,6),FALSE,K_SCROLL);
						good = FALSE;
				}
				if (good) {
					mpos = 0;
					msg("Enchanted %s.",inv_name(lb,TRUE));
				}
			}
			s_know[S_ALLENCH] = TRUE;
		}
	when S_BLESS:
		if (!curse) {
			struct linked_list *ll;
			struct object *lb;

			msg("Your pack glistens brightly.");
			for (ll = pack ; ll != NULL ; ll = next(ll)) {
				whatis(ll);
				lb = OBJPTR(ll);
				resoflg(lb,ISCURSED);
				setoflg(lb,ISBLESS);
			}
		}
	when S_MAKEIT:
		if (!curse) {
			msg("You have been endowed with the power of creation.");
			s_know[S_MAKEIT] = TRUE;
			create_obj(TRUE);
		}
	when S_BAN: {
		int howdeep;
		char *ptr;

		if (bless) {
			if (level > 6) {
				howdeep = 1 + rnd(5);
				ptr = "elevated to the upper";
			}
			else {
				howdeep = -1;
				bless = FALSE;
			}
		}
		else {
			howdeep = level + 10 + rnd(20) + (curse * 20);
			ptr = "banished to the lower";
		}
		if ((!bless && level < howdeep) || bless) {
			level = howdeep;
			new_level(NORMLEV);
			mpos = 0;
			msg("You are %s regions.", ptr);
			s_know[S_BAN] = TRUE;
		}
	}
	when S_CWAND:
		if (!curse) {
			struct linked_list *ll;
			struct object *lb;
			bool wands = FALSE;

			for (ll = pack ; ll != NULL ; ll = next(ll)) {
				lb = OBJPTR(ll);
				if (lb->o_type == STICK) {
					whatis(ll);
					setoflg(lb, ISKNOW);
					resoflg(lb, ISCURSED);
					lb->o_charges += rnd(11) + 5;
					wands = TRUE;
				}
			}
			if (wands) {
				msg("Your sticks gleam.");
				s_know[wh] = TRUE;
			}
		}
	when S_LOCTRAP: {
		struct trap *trp;

		if (ntraps > 0) {
			for (trp = &traps[0]; trp < &traps[ntraps]; trp++)
				trp->tr_flags |= ISFOUND;
			look(FALSE);
			msg("You now recognize pitfalls.");
			s_know[S_LOCTRAP] = TRUE;
		}
	}
	otherwise:
		msg("What a puzzling scroll!");
		return 0;
	}
コード例 #22
0
int
chase(struct thing *tp, coord *ee, int flee)
{
    int x, y;
    int dist, thisdist, monst_dist = INT_MAX;
    struct linked_list  *weapon;
    coord   *er = &tp->t_pos;
    coord shoot;
    coord *shootit_dir = NULL;
    int ch;
    char   mch;
    int    next_player = FALSE;

    /* Take care of shooting directions */

    if (on(*tp, CANBREATHE) || on(*tp, CANSHOOT) || on(*tp, CANCAST))
    {
        if (good_monster(*tp))
        {
            shootit_dir = find_shoot(tp, &shoot); /* find a mean monster */

            if (wizard && shootit_dir)
                msg("Found monster to attack towards (%d,%d).",
                    shootit_dir->x, shootit_dir->y);
        }
        else
            shootit_dir = can_shoot(er, ee, &shoot);  /* shoot hero */
    }

    /*
     * If the thing is confused, let it move randomly. Some monsters are
     * slightly confused all of the time.
     */

    if ((on(*tp, ISHUH) && rnd(10) < 8) ||
        ((on(*tp, ISINVIS) || on(*tp, ISSHADOW)) && rnd(100) < 20) ||
        (on(player, ISINVIS) && off(*tp, CANSEE)))
    {   /* Player is invisible */

        /* get a valid random move */

        tp->t_nxtpos = rndmove(tp);

        dist = DISTANCE(tp->t_nxtpos, *ee);

        if (on(*tp, ISHUH) && rnd(20) == 0) /* monster might lose confusion */
            turn_off(*tp, ISHUH);

        /*
         * check to see if random move takes creature away from
         * player if it does then turn off ISHELD
         */

        if (dist > 1 && on(*tp, DIDHOLD))
        {
            turn_off(*tp, DIDHOLD);
            turn_on(*tp, CANHOLD);

            if (--hold_count == 0)
                turn_off(player, ISHELD);
        }
    } /* If we can breathe, we may do so */
    else if (on(*tp, CANBREATHE) && (shootit_dir) && (rnd(100) < 67) &&
         (off(player, ISDISGUISE) || (rnd(tp->t_stats.s_lvl) > 6)) &&
         (DISTANCE(*er, *ee) < BOLT_LENGTH * BOLT_LENGTH))
    {
        int   chance;
        char    *breath;

        /* Will it breathe at random */

        if (on(*tp, CANBRANDOM))
        {
            if (rnd(level / 20) == 0 && tp->t_index != nummonst + 1
                && !(good_monster(*tp)))
                turn_off(*tp, CANBRANDOM);

            /* Select type of breath */

            chance = rnd(100);

            if (chance < 11)
                breath = "acid";
            else if (chance < 22)
                breath = "flame";
            else if (chance < 33)
                breath = "lightning bolt";
            else if (chance < 44)
                breath = "chlorine gas";
            else if (chance < 55)
                breath = "ice";
            else if (chance < 66)
                breath = "nerve gas";
            else if (chance < 77)
                breath = "sleeping gas";
            else if (chance < 88)
                breath = "slow gas";
            else
                breath = "fear gas";
        } /* Or can it breathe acid? */
        else if (on(*tp, CANBACID))
        {
            if (!good_monster(*tp) && rnd(level / 15) == 0)
                turn_off(*tp, CANBACID);

            breath = "acid";
        } /* Or can it breathe fire */
        else if (on(*tp, CANBFIRE))
        {
            if (!good_monster(*tp) && rnd(level / 15) == 0)
                turn_off(*tp, CANBFIRE);

            breath = "flame";
        } /* Or can it breathe electricity? */
        else if (on(*tp, CANBBOLT))
        {
            if (!good_monster(*tp) && rnd(level / 15) == 0)
                turn_off(*tp, CANBBOLT);

            breath = "lightning bolt";
        } /* Or can it breathe gas? */
        else if (on(*tp, CANBGAS))
        {
            if (!good_monster(*tp) && rnd(level / 15) == 0)
                turn_off(*tp, CANBGAS);

            breath = "chlorine gas";
        } /* Or can it breathe ice? */
        else if (on(*tp, CANBICE))
        {
            if (!good_monster(*tp) && rnd(level / 15) == 0)
                turn_off(*tp, CANBICE);

            breath = "ice";
        }
        else if (on(*tp, CANBPGAS))
        {
            if (!good_monster(*tp) && rnd(level / 15) == 0)
                turn_off(*tp, CANBPGAS);

            breath = "nerve gas";
        }
        else if (on(*tp, CANBSGAS))
        {
            if (!good_monster(*tp) && rnd(level / 15) == 0)
                turn_off(*tp, CANBSGAS);

            breath = "sleeping gas";
        }
        else if (on(*tp, CANBSLGAS))
        {
            if (!good_monster(*tp) && rnd(level / 15) == 0)
                turn_off(*tp, CANBSLGAS);

            breath = "slow gas";
        }
        else
        {
            if (!good_monster(*tp) && rnd(level / 15) == 0)
                turn_off(*tp, CANBFGAS);

            breath = "fear gas";
        }

        shoot_bolt(tp, *er, *shootit_dir, (tp == THINGPTR(fam_ptr)),
               tp->t_index, breath, roll(tp->t_stats.s_lvl, 6));

        tp->t_nxtpos = *er;

        dist = DISTANCE(tp->t_nxtpos, *ee);

        if (!curr_mons)
            return (TRUE);
    }
    else if (shootit_dir && on(*tp, CANCAST) &&
         (off(player, ISDISGUISE) || (rnd(tp->t_stats.s_lvl) > 6)))
    {
        /*
            If we can cast spells we might do so - even if adjacent fleeing
            monsters are restricted to certain spells
        */

        incant(tp, *shootit_dir);
        tp->t_nxtpos = *er;
        dist = DISTANCE(tp->t_nxtpos, *ee);
    }
    else if (shootit_dir && on(*tp, CANSHOOT)) 
    {
	weapon = get_hurl(tp);
	
	if (weapon &&
         (off(*tp, ISFLEE) || rnd(DISTANCE(*er, *ee)) > 2) &&
         (off(player, ISDISGUISE) || (rnd(tp->t_stats.s_lvl) > 6)))
	{
	    /*
	        Should we shoot or throw something? fleeing monsters 
		may to shoot anyway if far enough away
	    */

	    missile(shootit_dir->y, shootit_dir->x, weapon, tp);
	    tp->t_nxtpos = *er;
	    dist = DISTANCE(tp->t_nxtpos, *ee);
	}
    }
    else
    {
        /*
            Otherwise, find the empty spot next to the chaser that is closest
            to the chasee.
        */
        int ey, ex;
        struct room *rer, *ree;
        int dist_to_old = INT_MIN;   /* Dist from goal to old position */

        /* Get rooms */
        rer = roomin(*er);
        ree = roomin(*ee);

        /*
         * This will eventually hold where we move to get closer. If
         * we can't find an empty spot, we stay where we are.
         */

        dist = flee ? 0 : INT_MAX;
        tp->t_nxtpos = *er;

        /* Are we at our goal already? */

        if (!flee && ce(tp->t_nxtpos, *ee))
            return (FALSE);

        ey = er->y + 1;
        ex = er->x + 1;

        for (x = er->x - 1; x <= ex; x++)
            for (y = er->y - 1; y <= ey; y++)
            {
                coord   tryp; /* test position */

                /* Don't try off the screen */

                if ((x < 0) || (x >= COLS) || (y < 1) || (y >= LINES - 2))
                    continue;

                /*
                 * Don't try the player if not going after
                 * the player or he's disguised and monster is dumb
                 */

                if (((off(*tp, ISFLEE) && !ce(hero, *ee)) ||
                     (on(player, ISDISGUISE) && (rnd(tp->t_stats.s_lvl) < 6))
                     || good_monster(*tp))
                    && x == hero.x && y == hero.y)
                    continue;

                tryp.x = x;
                tryp.y = y;

                /*
                 * Is there a monster on this spot closer to
                 * our goal? Don't look in our spot or where
                 * we were.
                 */

                if (!ce(tryp, *er) && !ce(tryp, tp->t_oldpos) &&
                    isalpha( (mch = CCHAR(mvwinch(mw, y, x))) ) )
                {
                    int test_dist;

                    test_dist = DISTANCE(tryp,*ee);
                    if (test_dist <= 25 &&  /* Let's be fairly close */
                        test_dist < monst_dist)
                    {

                        /* Could we really move there? */

                        mvwaddch(mw, y, x, ' '); /* Temp blank monst */

                        if (diag_ok(er, &tryp, tp))
                            monst_dist = test_dist;

                        mvwaddch(mw, y, x, mch);    /* Restore monster */
                    }
                }

                if (!diag_ok(er, &tryp, tp))
                    continue;

                ch = mvwinch(cw, y, x); /* Screen character */

                /*
                 * Stepping on player is NOT okay if we are
                 * fleeing
                 */

                if (on(*tp, ISFLEE) && (ch == PLAYER))
				    next_player = TRUE;
					
                if (step_ok(y, x, NOMONST, tp) &&
                    (off(*tp, ISFLEE) || ch != PLAYER))
                {

                    /*
                     * If it is a trap, an intelligent
                     * monster may not step on it (unless
                     * our hero is on top!)
                     */

                    if (isatrap(ch))
                    {
                        if (!(ch == RUSTTRAP) &&
                            !(ch == FIRETRAP && on(*tp, NOFIRE)) &&
                            rnd(10) < tp->t_stats.s_intel &&
                        (y != hero.y || x != hero.x))
                            continue;
                    }

                    /*
                     * OK -- this place counts
                     */

                    thisdist = DISTANCE(tryp, *ee);
					
                    /*
                     * Adjust distance if we are being
                     * shot at to moving out of line of sight.
                     */

                    if (tp->t_wasshot && tp->t_stats.s_intel > 5 &&
                        ce(hero, *ee))
                    {
                        /* Move out of line of sight */
                        if (straight_shot(tryp.y, tryp.x, ee->y, ee->x, NULL))
                        {
                            if (flee)
                                thisdist -= SHOTPENALTY;
                            else
                                thisdist += SHOTPENALTY;
                        }

                        /*
                         * But do we want to leave
                         * the room?
                         */
                        else if (rer && rer == ree && ch == DOOR)
                            thisdist += DOORPENALTY;
                    }

                    /*
                     * Don't move to the last position if
                     * we can help it
                     */

                    if (ce(tryp, tp->t_oldpos))
                        dist_to_old = thisdist;
                    else if ((flee && (thisdist > dist)) ||
                         (!flee && (thisdist < dist)))
                    {
                        tp->t_nxtpos = tryp;
                        dist = thisdist;
                    }
                }
            }

        /*
         * If we are running from the player and he is in our way, go
         * ahead and slug him.
         */

        if (next_player && DISTANCE(*er,*ee) < dist &&
            step_ok(tp->t_chasee->t_pos.y, tp->t_chasee->t_pos.x, NOMONST, tp))
        {
            tp->t_nxtpos = tp->t_chasee->t_pos;    /* Okay to hit player */
            return(FALSE);
        }


        /*
         * If we can't get closer to the player (if that's our goal)
         * because other monsters are in the way, just stay put
         */

        if (!flee && ce(hero, *ee) && monst_dist < INT_MAX &&
            DISTANCE(*er, hero) < dist)
            tp->t_nxtpos = *er;

        /* Do we want to go back to the last position? */
        else if (dist_to_old != INT_MIN &&   /* It is possible to move back */
             ((flee && dist == 0) ||        /* No other possible moves */
              (!flee && dist == INT_MAX)))
        {
            /* Do we move back or just stay put (default)? */

            dist = DISTANCE(*er,*ee); /* Current distance */

            if (!flee || (flee && (dist_to_old > dist)))
                tp->t_nxtpos = tp->t_oldpos;
        }
    }

    /* Make sure we have the real distance now */
    dist = DISTANCE(tp->t_nxtpos, *ee);

    /* Mark monsters in a wall */

    switch(mvinch(tp->t_nxtpos.y, tp->t_nxtpos.x))
    {
        case WALL:
        case '-':
        case '|':
            turn_on(*tp, ISINWALL);
            break;
        default:
            turn_off(*tp, ISINWALL);
    }

    if (off(*tp, ISFLEE) &&
        !(!SAME_POS((tp->t_chasee->t_pos),hero) || off(player, ISINWALL) || on(*tp, CANINWALL)))
        return(dist != 0);
    else /* May actually hit here from a confused move */
        return(!ce(tp->t_nxtpos, hero));
}
コード例 #23
0
int
add_pack(struct linked_list *item, int print_message)
{
    struct object   *obj, *op;
    int from_floor;

    if (item == NULL)
    {
        from_floor = TRUE;

        if ((item = find_obj(hero.y, hero.x)) == NULL)
        {
            msg("Nothing to pick up.");
            return(FALSE);
        }
    }
    else
        from_floor = FALSE;

    if (from_floor)
    {
        item = get_stack(item);

        if (!item)
            return(FALSE);
    }

    obj = OBJPTR(item);

    /* If it is gold, just add its value to rogue's purse and get rid of */

    if (obj->o_type == GOLD)
    {
        struct linked_list  *mitem;
        struct thing    *tp;

        if (print_message)
        {
            if (!terse)
                addmsg("You found ");

            msg("%d gold pieces.", obj->o_count);
        }

        /*
         * First make sure no greedy monster is after this gold. If
         * so, make the monster run after the rogue instead.
         */

        for (mitem = mlist; mitem != NULL; mitem = next(mitem))
        {
            tp = THINGPTR(mitem);

            if (tp->t_horde==obj)
            {
                tp->t_ischasing = TRUE;
                tp->t_chasee = &player;
                tp->t_horde  = NULL;
            }
        }

        /*
         * This will cause problems if people are able to drop and
         * pick up gold, or when GOLDSTEAL monsters are killed.
         */

        /* Thieves get EXP for gold they pick up */

        if (player.t_ctype == C_THIEF)
        {
            pstats.s_exp += obj->o_count / 4;
            check_level();
        }

        purse += obj->o_count;

        if (from_floor)
            rem_obj(item, TRUE);    /* Remove object from the level */

        return (TRUE);
    }

    /* see if he can carry any more weight */

    if (itemweight(obj) + pstats.s_pack > pstats.s_carry)
    {
        msg("Too much for you to carry.");

        if (print_message)
        {
            msg("%s onto %s", terse ? "Moved" : "You moved",
                inv_name(obj, LOWERCASE));
        }

        return(FALSE);
    }

    /*
     * Link it into the pack. If the item can be grouped, try to find its
     * neighbors and bump the count. A special case is food, which can't
     * be grouped, but an exact match allows the count to get
     * incremented.
     */

    if ((op = apply_to_bag(pack, obj->o_type, bff_group, NULL, obj)) != NULL)
    {
        op->o_count += obj->o_count;    /* add it to the rest */

        if (from_floor)
            rem_obj(item, FALSE);

        pack_report(op, print_message, "You now have ");

        return(TRUE);
    }

    /* Check for and deal with scare monster scrolls */

    if (obj->o_type == SCROLL && obj->o_which == S_SCARE)
        if (obj->o_flags & ISCURSED)
        {
            msg("The scroll turns to dust as you pick it up.");
            rem_obj(item, TRUE);
            return(TRUE);
        }

    /* Check if there is room */

    if (count_bag(pack, obj->o_type, NULL) == max_print())
    {
        msg("You have no room for more %s.", name_type(obj->o_type));

        if (print_message)
        {
            obj = OBJPTR(item);
            msg("%s onto %s.", terse ? "Moved" : "You moved",
                inv_name(obj, LOWERCASE));
        }

        return(FALSE);
    }

    /*
     * finally, add the new item to the bag, and free up the linked list
     * on top of it.
     */

    if (from_floor)
        rem_obj(item, FALSE);

    push_bag(&pack, obj);
    pack_report(obj, print_message, "You now have ");
    ur_free(item);

    return(TRUE);      /* signal success */
}
コード例 #24
0
daemon
runners(daemon_arg *arg)
{
    struct linked_list  *item;
    struct thing        *tp;

    NOOP(arg);

    for (item = mlist; item != NULL; item = next_mons)
    {
        curr_mons = item;
        next_mons = next(curr_mons);
        tp        = THINGPTR(item);

        if (on(*tp, ISHELD) && rnd(tp->t_stats.s_str +
            tp->t_stats.s_lvl) > 10 + rnd(50))
        {
            turn_off(*tp, ISHELD);
            turn_off(*tp, ISDISGUISE);
            turn_on(*tp, ISRUN);
            tp->t_ischasing = TRUE;
            tp->t_chasee = &player;
            tp->t_horde  = NULL;

            if (tp->t_stats.s_hpt < rnd(tp->maxstats.s_hpt))
                turn_on(*tp, ISFLEE);

            if (cansee(tp->t_pos.y, tp->t_pos.x))
                msg("The %s breaks free!", monsters[tp->t_index].m_name);
        }

        if (off(*tp, ISHELD) && on(*tp, ISRUN))
        {
            int flee = FALSE;

            flee = on(*tp, ISFLEE) ||
                     ( (tp->t_chasee == &player) &&
                         on(player, ISINWALL) &&
                         off(*tp, CANINWALL) && off(*tp, ISFAMILIAR) );

            if (off(*tp, ISSLOW) || tp->t_turn)
            {
                daemon_arg targ;

                targ.thingptr = tp;
                doctor(&targ);
                do_chase(tp, flee);
            }

            if (curr_mons && (on(*tp, ISHASTE) ||
               ((on(*tp, CANFLY) || on(*tp, ISFAST)) &&
               DISTANCE(hero, tp->t_pos) >= 4)))
            {
                daemon_arg targ;

                targ.thingptr = tp;
                doctor(&targ);
                do_chase(tp, flee);
            }

            if (curr_mons)
            {
                tp->t_turn ^= TRUE;
                tp->t_wasshot ^= FALSE; /* Not shot anymore */
            }

        }
    }

    curr_mons = next_mons = NULL;

    return;
}