예제 #1
0
void StatusMonitor::diagnosticStatus(const ros::TimerEvent& time)
{
	if ((double)ros::Time::now().toSec() - (double)last_status_.toSec() > TIMEOUT){
		diag_error("CONTROLLER TIMEOUT");
	}
	else if (status_ == 0){
		diag_ok(info_);
	}
	else if (status_ == 1){
		diag_warn(info_);
	}
	else if (status_ == 2){
		diag_error(info_);
	}
}
예제 #2
0
파일: chase.c 프로젝트: kioy/TA-Demo2
/*
 * chase:
 *	Find the spot for the chaser(er) to move closer to the
 *	chasee(ee).  Returns TRUE if we want to keep on chasing later
 *	FALSE if we reach the goal.
 */
int
chase(THING *tp, const coord *ee)
{
    THING *obj;
    int x, y;
    int curdist, thisdist;
    const coord *er = &tp->t_pos;
    int ch;
    int plcnt = 1;
    coord tryp;

    /*
     * If the thing is confused, let it move randomly. Invisible
     * Stalkers are slightly confused all of the time, and bats are
     * quite confused all the time
     */
    if ((on(*tp, ISHUH) && rnd(5) != 0) || (tp->t_type == 'P' && rnd(5) == 0)
	|| (tp->t_type == 'B' && rnd(2) == 0))
    {
	/*
	 * get a valid random move
	 */
	ch_ret = rndmove(tp);
	curdist = dist_cp(&ch_ret, ee);
	/*
	 * Small chance that it will become un-confused 
	 */
	if (rnd(20) == 0)
	    tp->t_flags &= ~ISHUH;
    }
    /*
     * Otherwise, find the empty spot next to the chaser that is
     * closest to the chasee.
     */
    else
    {
	int ey, ex;
	/*
	 * This will eventually hold where we move to get closer
	 * If we can't find an empty spot, we stay where we are.
	 */
	curdist = dist_cp(er, ee);
	ch_ret = *er;

	ey = er->y + 1;
	if (ey >= NUMLINES - 1)
	    ey = NUMLINES - 2;
	ex = er->x + 1;
	if (ex >= NUMCOLS)
	    ex = NUMCOLS - 1;

	for (x = er->x - 1; x <= ex; x++)
	{
	    if (x < 0)
		continue;
	    tryp.x = x;
	    for (y = er->y - 1; y <= ey; y++)
	    {
		tryp.y = y;
		if (!diag_ok(er, &tryp))
		    continue;
		ch = winat(y, x);
		if (step_ok(ch))
		{
		    /*
		     * If it is a scroll, it might be a scare monster scroll
		     * so we need to look it up to see what type it is.
		     */
		    if (ch == SCROLL)
		    {
			for (obj = lvl_obj; obj != NULL; obj = next(obj))
			{
			    if (y == obj->o_pos.y && x == obj->o_pos.x)
				break;
			}
			if (obj != NULL && obj->o_which == S_SCARE)
			    continue;
		    }
		    /*
		     * It can also be a Xeroc, which we shouldn't step on
		     */
		    if ((obj = moat(y, x)) != NULL && obj->t_type == 'X')
			continue;
		    /*
		     * If we didn't find any scrolls at this place or it
		     * wasn't a scare scroll, then this place counts
		     */
		    thisdist = dist(y, x, ee->y, ee->x);
		    if (thisdist < curdist)
		    {
			plcnt = 1;
			ch_ret = tryp;
			curdist = thisdist;
		    }
		    else if (thisdist == curdist && rnd(++plcnt) == 0)
		    {
			ch_ret = tryp;
			curdist = thisdist;
		    }
		}
	    }
	}
    }
    return (curdist != 0 && !ce(ch_ret, hero));
}
예제 #3
0
int
chase(struct thing *tp, coord *ee)
{
    int x, y;
    int dist, thisdist;
    struct linked_list *item;
    struct object *obj;
    coord *er = &tp->t_pos;
    int ch;

    /*
     * If the thing is confused, let it move randomly. Invisible
     * Stalkers are slightly confused all of the time, and bats are
     * quite confused all the time
     */
    if ((on(*tp, ISHUH) && rnd(10) < 8) || (tp->t_type == 'I' && rnd(100) < 20)
	|| (tp->t_type == 'B' && rnd(100) < 50))
    {
	/*
	 * get a valid random move
	 */
	ch_ret = *rndmove(tp);
	dist = DISTANCE(ch_ret.y, ch_ret.x, ee->y, ee->x);
	/*
	 * Small chance that it will become un-confused 
	 */
	if (rnd(1000) < 50)
	    tp->t_flags &= ~ISHUH;
    }
    /*
     * Otherwise, find the empty spot next to the chaser that is
     * closest to the chasee.
     */
    else
    {
	int ey, ex;
	/*
	 * This will eventually hold where we move to get closer
	 * If we can't find an empty spot, we stay where we are.
	 */
	dist = DISTANCE(er->y, er->x, ee->y, ee->x);
	ch_ret = *er;

	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;

		tryp.x = x;
		tryp.y = y;
		if (!diag_ok(er, &tryp))
		    continue;
		ch = winat(y, x);
		if (step_ok(ch))
		{
		    /*
		     * If it is a scroll, it might be a scare monster scroll
		     * so we need to look it up to see what type it is.
		     */
		    if (ch == SCROLL)
		    {
			for (item = lvl_obj; item != NULL; item = next(item))
			{
			    obj = (struct object *) ldata(item);
			    if (y == obj->o_pos.y && x == obj->o_pos.x)
				break;
			}
			if (item != NULL && obj->o_which == S_SCARE)
			    continue;
		    }
		    /*
		     * If we didn't find any scrolls at this place or it
		     * wasn't a scare scroll, then this place counts
		     */
		    thisdist = DISTANCE(y, x, ee->y, ee->x);
		    if (thisdist < dist)
		    {
			ch_ret = tryp;
			dist = thisdist;
		    }
		}
	    }
    }
    return (dist != 0);
}
예제 #4
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));
}
예제 #5
0
int
can_blink(struct thing *tp)
{
    int   y, x, index = 9;
    coord   tryp;       /* To hold the coordinates for use in diag_ok */
    int    spots[9], found_one = FALSE;

    /*
     * First, can the monster even blink?  And if so, there is only a 30%
     * chance that it will do so.  And it won't blink if it is running.
     */

    if (off(*tp, CANBLINK) || (on(*tp, ISHELD)) ||
        on(*tp, ISFLEE) ||
        (on(*tp, ISSLOW) && off(*tp, ISHASTE) && !(tp->t_turn)) ||
        (rnd(10) < 9))
        return (FALSE);

    /* Initialize the spots as illegal */

    do
    {
        spots[--index] = FALSE;
    }
    while (index > 0);

    /* Find a suitable spot next to the player */

    for (y = hero.y - 1; y < hero.y + 2; y++)
        for (x = hero.x - 1; x < hero.x + 2; x++, index++)
        {
            /*
             * Make sure x coordinate is in range and that we are
             * not at the player's position
             */

            if (x < 0 || x >= COLS || index == 4)
                continue;

            /* Is it OK to move there? */

            if (!step_ok(y, x, NOMONST, tp))
                spots[index] = FALSE;
           else
           {

                /*
                 * OK, we can go here.  But don't go there if
                 * monster can't get at player from there
                 */

                tryp.y = y;
                tryp.x = x;
                if (diag_ok(&tryp, &hero, tp))
                {
                    spots[index] = TRUE;
                    found_one = TRUE;
                }
            }
        }

    /* If we found one, go to it */

    if (found_one)
    {
        /* Find a legal spot */

        while (spots[index = rnd(9)] == FALSE)
            continue;

        /* Get the coordinates */

        y = hero.y + (index / 3) - 1;
        x = hero.x + (index % 3) - 1;

        /* Move the monster from the old space */

        mvwaddch(cw, tp->t_pos.y, tp->t_pos.x, tp->t_oldch);

        /* Move it to the new space */

        tp->t_oldch = CCHAR( mvwinch(cw, y, x) );

        if (cansee(y, x) &&
            off(*tp, ISINWALL) &&
            ((off(*tp, ISINVIS) &&
              (off(*tp, ISSHADOW) || rnd(100) < 10)) || on(player, CANSEE)) &&
            off(*tp, CANSURPRISE))
            mvwaddch(cw, y, x, tp->t_type);

        mvwaddch(mw, tp->t_pos.y,tp->t_pos.x,' '); /*Clear old position */
        mvwaddch(mw, y, x, tp->t_type);
        tp->t_pos.y = y;
        tp->t_pos.x = x;
    }

    return (found_one);
}
/*
 * chase:
 *	Find the spot for the chaser(er) to move closer to the
 *	chasee(ee).  Returns TRUE if we want to keep on chasing later
 *	FALSE if we reach the goal.
 */
int
chase(struct thing *tp, coord *ee, int flee, int *mdead)
{
    register int x, y;
    register int dist, thisdist, monst_dist = MAXINT;
    register struct linked_list *weapon;
    register coord *er = &tp->t_pos, *shoot_dir;
    register int ch, mch;
    register int next_player = FALSE;
    int deadflg;

	if (mdead != NULL)
		*mdead = 0;

	shoot_dir = can_shoot(er, ee);
    weapon = get_hurl(tp);

    /*
     * If the thing is confused, let it move randomly. Invisible
     * Stalkers 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
	 */
	ch_ret = *rndmove(tp);
	dist = DISTANCE(ch_ret.y, ch_ret.x, ee->y, ee->x);

    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)
	    {
	        hold_count = 0;
	        turn_off(player, ISHELD);
	    }
	}
    }

    /* If we can breathe, we may do so */
    else if (on(*tp, CANBREATHE) && (shoot_dir) &&
	     (rnd(100) < 67) &&
		 (off(player, ISDISGUISE) || (rnd(tp->t_stats.s_lvl) > 6)) &&
	     (DISTANCE(er->y, er->x, ee->y, ee->x) < BOLT_LENGTH*BOLT_LENGTH)) {
		register int chance;
		register char *breath;

		/* Will it breathe at random */
		if (on(*tp, CANBRANDOM)) {
		    if (rnd(level/20) == 0 && tp->t_index != NUMMONST+1)
			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 (rnd(level/20) == 0)
			turn_off(*tp, CANBACID);
		    breath = "acid";
		}

		/* Or can it breathe fire */
		else if (on(*tp, CANBFIRE)) {
		    if (rnd(level/20) == 0)
			turn_off(*tp, CANBFIRE);
		    breath = "flame";
		}

		/* Or can it breathe electricity? */
		else if (on(*tp, CANBBOLT)) {
		    if (rnd(level/20) == 0)
			turn_off(*tp, CANBBOLT);
		    breath = "lightning bolt";
		}

		/* Or can it breathe gas? */
		else if (on(*tp, CANBGAS)) {
		    if (rnd(level/20) == 0)
			turn_off(*tp, CANBGAS);
		    breath = "chlorine gas";
		}

		/* Or can it breathe ice? */
		else if (on(*tp, CANBICE)) {
		    if (rnd(level/20) == 0)
			turn_off(*tp, CANBICE);
		    breath = "ice";
		}

		else if (on(*tp, CANBPGAS)) {
		    if (rnd(level/20) == 0)
			turn_off(*tp, CANBPGAS);
		    breath = "nerve gas";
		}

		else if (on(*tp, CANBSGAS)) {
		    if (rnd(level/20) == 0)
			turn_off(*tp, CANBSGAS);
		    breath = "sleeping gas";
		}

		else if (on(*tp, CANBSLGAS)) {
		    if (rnd(level/20) == 0)
			turn_off(*tp, CANBSLGAS);
		    breath = "slow gas";
		}

		else {
		    if (rnd(level/20) == 0)
			turn_off(*tp, CANBFGAS);
		    breath = "fear gas";
		}

		/* Now breathe -- returns TRUE if kills itself */
		deadflg =
		    shoot_bolt(tp, *er, *shoot_dir, FALSE, tp->t_index, breath,
			       (save(VS_BREATH) ? tp->t_stats.s_hpt/2
					        : tp->t_stats.s_hpt));

		if (deadflg && mdead != NULL)
			*mdead = 1;

		ch_ret = *er;
		dist = DISTANCE(ch_ret.y, ch_ret.x, ee->y, ee->x);
		if (deadflg) return(TRUE);
	}

    /* 
     * If we can shoot or throw something, we might do so 
     * if we are running away, we may decide to shoot anyway if we are far 
     * enough
     */
    else if((off(*tp, ISFLEE) || rnd(DISTANCE(er->y,er->x,ee->y,ee->x)) > 2) && 
	     on(*tp, CANSHOOT) && (off(player, ISDISGUISE) ||
		 (rnd(tp->t_stats.s_lvl) > 6)) &&
	    (shoot_dir) &&
	    (weapon)) {
		missile(shoot_dir->y, shoot_dir->x, weapon, tp);
		ch_ret = *er;
		dist = DISTANCE(ch_ret.y, ch_ret.x, ee->y, ee->x);
	}

    /*
     * Otherwise, find the empty spot next to the chaser that is
     * closest to the chasee.
     */
    else {
	register int ey, ex;
	register struct room *rer, *ree;
	register int dist_to_old = MININT; /* 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 : MAXINT;
	ch_ret = *er;

	/* Are we at our goal already? */
	if (!flee && ce(ch_ret, *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;

		/* Don't try off the board */
		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 */
		if ( ((off(*tp, ISFLEE) && !ce(hero, *ee)) ||
			(on(player, ISDISGUISE) && (rnd(tp->t_stats.s_lvl) < 6))) &&
			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) ))) {
		    register int test_dist;

		    test_dist = DISTANCE(y, x, ee->y, ee->x);
		    if (test_dist <= 25 &&   /* Let's be fairly close */
			test_dist < monst_dist) {
			/* Could we really move there? */
			mvwaddch(mw, y, x, ' '); /* Temporarily 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 = CCHAR( mvwinch(cw, y, x) );	/* Screen character */
		if (on(*tp, ISFLEE) && (ch == PLAYER)) next_player = TRUE;

		/* Stepping on player is NOT okay if we are fleeing */
		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(y, x, ee->y, ee->x);

		    /* Adjust distance if we are being shot at */
		    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)))
		    {
			ch_ret = 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->y, er->x, ee->y, ee->x) < dist &&
	    step_ok(tp->t_dest->y, tp->t_dest->x, NOMONST, tp)) {
	    ch_ret = *(tp->t_dest);	/* 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 < MAXINT &&
	    DISTANCE(er->y, er->x, hero.y, hero.x) < dist)
		ch_ret = *er;

	/* Do we want to go back to the last position? */
	else if (dist_to_old != MININT &&      /* It is possible to move back */
	    ((flee && dist == 0) ||	/* No other possible moves */
	     (!flee && dist == MAXINT))) {
	    /* Do we move back or just stay put (default)? */
	    dist = DISTANCE(er->y, er->x, ee->y, ee->x); /* Current distance */
	    if (!flee || (flee && (dist_to_old > dist))) ch_ret = tp->t_oldpos;
	}
    }

    /* Make sure we have the real distance now */
    dist = DISTANCE(ch_ret.y, ch_ret.x, ee->y, ee->x);

    /* Mark monsters in a wall */
    if (isrock(CCHAR( mvinch(ch_ret.y, ch_ret.x) ))) 
	turn_on(*tp, ISINWALL);
    else 
	turn_off(*tp, ISINWALL);

    if (off(*tp, ISFLEE) &&
	((tp->t_dest != &hero) || off(player, ISINWALL) || on(*tp, CANINWALL)))
	return (dist != 0);

    /* May actually hit here from a confused move */
    else return(!ce(ch_ret, hero));
}
예제 #7
0
파일: chase.cpp 프로젝트: daid/Rogue
    coord solve(coord start, coord end)
    {
        this->end = end;

        coord co;
        co.x = start.x;
        co.y = start.y - 1;
        addToList(co.x, co.y, co, 1);
        co.x = start.x - 1;
        co.y = start.y;
        addToList(co.x, co.y, co, 1);
        co.x = start.x + 1;
        co.y = start.y;
        addToList(co.x, co.y, co, 1);
        co.x = start.x;
        co.y = start.y + 1;
        addToList(co.x, co.y, co, 1);

        co.x = start.x - 1;
        co.y = start.y - 1;
        if (diag_ok(&start, &co)) addToList(co.x, co.y, co, 1);
        co.x = start.x + 1;
        co.y = start.y - 1;
        if (diag_ok(&start, &co)) addToList(co.x, co.y, co, 1);
        co.x = start.x - 1;
        co.y = start.y + 1;
        if (diag_ok(&start, &co)) addToList(co.x, co.y, co, 1);
        co.x = start.x + 1;
        co.y = start.y + 1;
        if (diag_ok(&start, &co)) addToList(co.x, co.y, co, 1);

        while(open_list.size() > 0)
        {
            int pos = open_list.front();
            open_list.pop_front();

            int score = info[pos].base_score;
            coord origin = info[pos].origin;

            co.x = pos & 0xFFFF;
            co.y = pos >> 16;
            if (ce(co, end))
                return origin;

            addToList(co.x,     co.y - 1, origin, score + 1);
            addToList(co.x - 1, co.y,     origin, score + 1);
            addToList(co.x + 1, co.y,     origin, score + 1);
            addToList(co.x,     co.y + 1, origin, score + 1);

            coord ct;
            ct.x = co.x - 1;
            ct.y = co.y - 1;
            if (diag_ok(&co, &ct)) addToList(ct.x, ct.y, origin, score + 1);
            ct.x = co.x + 1;
            ct.y = co.y - 1;
            if (diag_ok(&co, &ct)) addToList(ct.x, ct.y, origin, score + 1);
            ct.x = co.x - 1;
            ct.y = co.y + 1;
            if (diag_ok(&co, &ct)) addToList(ct.x, ct.y, origin, score + 1);
            ct.x = co.x + 1;
            ct.y = co.y + 1;
            if (diag_ok(&co, &ct)) addToList(ct.x, ct.y, origin, score + 1);
        }
        return start;
    }