示例#1
0
/* Mark locations that are temporarily lit via mobile light sources. */
void
do_light_sources(char **cs_rows)
{
    int x, y, min_x, max_x, max_y, offset;
    const char *limits;
    short at_hero_range = 0;
    light_source *ls;
    char *row;

    for (ls = level->lev_lights; ls; ls = ls->next) {
        ls->flags &= ~LSF_SHOW;

        /* 
         * Check for moved light sources.  It may be possible to
         * save some effort if an object has not moved, but not in
         * the current setup -- we need to recalculate for every
         * vision recalc.
         */
        if (ls->type == LS_OBJECT) {
            if (get_obj_location((struct obj *)ls->id, &ls->x, &ls->y, 0))
                ls->flags |= LSF_SHOW;
        } else if (ls->type == LS_MONSTER) {
            if (get_mon_location((struct monst *)ls->id, &ls->x, &ls->y, 0))
                ls->flags |= LSF_SHOW;
        }

        /* minor optimization: don't bother with duplicate light sources at
           hero */
        if (ls->x == u.ux && ls->y == u.uy) {
            if (at_hero_range >= ls->range)
                ls->flags &= ~LSF_SHOW;
            else
                at_hero_range = ls->range;
        }

        if (ls->flags & LSF_SHOW) {
            /* 
             * Walk the points in the circle and see if they are
             * visible from the center.  If so, mark'em.
             *
             * Kevin's tests indicated that doing this brute-force
             * method is faster for radius <= 3 (or so).
             */
            limits = circle_ptr(ls->range);
            if ((max_y = (ls->y + ls->range)) >= ROWNO)
                max_y = ROWNO - 1;
            if ((y = (ls->y - ls->range)) < 0)
                y = 0;
            for (; y <= max_y; y++) {
                row = cs_rows[y];
                offset = limits[abs(y - ls->y)];
                if ((min_x = (ls->x - offset)) < 0)
                    min_x = 0;
                if ((max_x = (ls->x + offset)) >= COLNO)
                    max_x = COLNO - 1;

                for (x = min_x; x <= max_x; x++)
                    if (clear_path((int)ls->x, (int)ls->y, x, y, cs_rows))
                        row[x] |= TEMP_LIT;
            }
        }
    }
}
示例#2
0
文件: light.c 项目: DanielT/NitroHack
/* Mark locations that are temporarily lit via mobile light sources. */
void do_light_sources(char **cs_rows)
{
    int x, y, min_x, max_x, max_y, offset;
    const char *limits;
    short at_hero_range = 0;
    light_source *ls;
    char *row;

    for (ls = level->lev_lights; ls; ls = ls->next) {
	ls->flags &= ~LSF_SHOW;

	/*
	 * Check for moved light sources.  It may be possible to
	 * save some effort if an object has not moved, but not in
	 * the current setup -- we need to recalculate for every
	 * vision recalc.
	 */
	if (ls->type == LS_OBJECT) {
	    if (get_obj_location((struct obj *) ls->id, &ls->x, &ls->y, 0))
		ls->flags |= LSF_SHOW;
	} else if (ls->type == LS_MONSTER) {
	    if (get_mon_location((struct monst *) ls->id, &ls->x, &ls->y, 0))
		ls->flags |= LSF_SHOW;
	}

	/* minor optimization: don't bother with duplicate light sources */
	/* at hero */
	if (ls->x == u.ux && ls->y == u.uy) {
	    if (at_hero_range >= ls->range)
		ls->flags &= ~LSF_SHOW;
	    else
		at_hero_range = ls->range;
	}

	if (ls->flags & LSF_SHOW) {
	    /*
	     * Walk the points in the circle and see if they are
	     * visible from the center.  If so, mark'em.
	     *
	     * Kevin's tests indicated that doing this brute-force
	     * method is faster for radius <= 3 (or so).
	     */
	    limits = circle_ptr(ls->range);
	    if ((max_y = (ls->y + ls->range)) >= ROWNO) max_y = ROWNO-1;
	    if ((y = (ls->y - ls->range)) < 0) y = 0;
	    for (; y <= max_y; y++) {
		row = cs_rows[y];
		offset = limits[abs(y - ls->y)];
		if ((min_x = (ls->x - offset)) < 0) min_x = 0;
		if ((max_x = (ls->x + offset)) >= COLNO) max_x = COLNO-1;

		if (ls->x == u.ux && ls->y == u.uy) {
		    /*
		     * If the light source is located at the hero, then
		     * we can use the COULD_SEE bits already calcualted
		     * by the vision system.  More importantly than
		     * this optimization, is that it allows the vision
		     * system to correct problems with clear_path().
		     * The function clear_path() is a simple LOS
		     * path checker that doesn't go out of its way
		     * make things look "correct".  The vision system
		     * does this.
		     */
		    for (x = min_x; x <= max_x; x++)
			if (row[x] & COULD_SEE)
			    row[x] |= TEMP_LIT;
		} else {
		    for (x = min_x; x <= max_x; x++)
			if ((ls->x == x && ls->y == y)
				|| clear_path((int)ls->x, (int) ls->y, x, y))
			    row[x] |= TEMP_LIT;
		}
	    }
	}
    }
}
示例#3
0
文件: dog.c 项目: wheals/nethack4
/* called from resurrect() in addition to losedogs() */
void
mon_arrive(struct monst *mtmp, boolean with_you)
{
    struct trap *t;
    struct obj *otmp;
    xchar xlocale, ylocale, xyloc, xyflags, wander;
    int num_segs;

    mtmp->dlevel = level;
    mtmp->nmon = level->monlist;
    level->monlist = mtmp;
    if (mtmp->isshk)
        set_residency(mtmp, FALSE);

    num_segs = mtmp->wormno;
    /* baby long worms have no tail so don't use is_longworm() */
    if ((mtmp->data == &mons[PM_LONG_WORM]) &&
        (mtmp->wormno = get_wormno(mtmp->dlevel)) != 0) {
        initworm(mtmp, num_segs);
        /* tail segs are not yet initialized or displayed */
    } else
        mtmp->wormno = 0;

    /* some monsters might need to do something special upon arrival _after_
       the current level has been fully set up; see dochug() */
    mtmp->mstrategy |= STRAT_ARRIVE;

    xyloc = mtmp->xyloc;
    xyflags = mtmp->xyflags;
    xlocale = mtmp->xlocale;
    ylocale = mtmp->ylocale;

    for (otmp = mtmp->minvent; otmp; otmp = otmp->nobj)
        set_obj_level(mtmp->dlevel, otmp);

    if (mtmp == u.usteed)
        return; /* don't place steed on the map */
    if (with_you) {
        /* When a monster accompanies you, sometimes it will arrive at your
           intended destination and you'll end up next to that spot.  This code
           doesn't control the final outcome; goto_level(do.c) decides who ends
           up at your target spot when there is a monster there too. */
        if (!MON_AT(level, u.ux, u.uy) &&
            !rn2(mtmp->mtame ? 10 : mtmp->mpeaceful ? 5 : 2))
            rloc_to(mtmp, u.ux, u.uy);
        else
            mnexto(mtmp);
        return;
    }
    /*
     * The monster arrived on this level independently of the player.
     * Its coordinate fields were overloaded for use as flags that
     * specify its final destination.
     */

    if (mtmp->mlstmv < moves - 1L) {
        /* heal monster for time spent in limbo */
        long nmv = moves - 1L - mtmp->mlstmv;

        mon_catchup_elapsed_time(mtmp, nmv);
        mtmp->mlstmv = moves - 1L;

        /* let monster move a bit on new level (see placement code below) */
        wander = (xchar) min(nmv, 8);
    } else
        wander = 0;

    switch (xyloc) {
    case MIGR_APPROX_XY:       /* {x,y}locale set above */
        break;
    case MIGR_EXACT_XY:
        wander = 0;
        break;
    case MIGR_NEAR_PLAYER:
        xlocale = u.ux, ylocale = u.uy;
        break;
    case MIGR_STAIRS_UP:
        xlocale = level->upstair.sx, ylocale = level->upstair.sy;
        break;
    case MIGR_STAIRS_DOWN:
        xlocale = level->dnstair.sx, ylocale = level->dnstair.sy;
        break;
    case MIGR_LADDER_UP:
        xlocale = level->upladder.sx, ylocale = level->upladder.sy;
        break;
    case MIGR_LADDER_DOWN:
        xlocale = level->dnladder.sx, ylocale = level->dnladder.sy;
        break;
    case MIGR_SSTAIRS:
        xlocale = level->sstairs.sx, ylocale = level->sstairs.sy;
        break;
    case MIGR_PORTAL:
        if (In_endgame(&u.uz)) {
            /* there is no arrival portal for endgame levels */
            /* BUG[?]: for simplicity, this code relies on the fact that we
               know that the current endgame levels always build upwards and
               never have any exclusion subregion inside their TELEPORT_REGION
               settings. */
            xlocale =
                rn1(level->updest.hx - level->updest.lx + 1, level->updest.lx);
            ylocale =
                rn1(level->updest.hy - level->updest.ly + 1, level->updest.ly);
            break;
        }
        /* find the arrival portal */
        for (t = level->lev_traps; t; t = t->ntrap)
            if (t->ttyp == MAGIC_PORTAL)
                break;
        if (t) {
            xlocale = t->tx, ylocale = t->ty;
            break;
        } else {
            impossible("mon_arrive: no corresponding portal?");
        }
     /*FALLTHRU*/ default:
    case MIGR_RANDOM:
        xlocale = COLNO;
        ylocale = ROWNO;
        break;
    }

    if ((xlocale != COLNO) && wander) {
        /* monster moved a bit; pick a nearby location */
        /* mnearto() deals w/stone, et al */
        char *r = in_rooms(level, xlocale, ylocale, 0);

        if (r && *r) {
            coord c;

            /* somexy() handles irregular level->rooms */
            if (somexy(level, &level->rooms[*r - ROOMOFFSET], &c, rng_main))
                xlocale = c.x, ylocale = c.y;
            else {
                xlocale = COLNO;
                ylocale = ROWNO;
            }
        } else {        /* not in a room */
            int i, j;

            i = max(0, xlocale - wander);
            j = min(COLNO - 1, xlocale + wander);
            xlocale = rn1(j - i, i);
            i = max(0, ylocale - wander);
            j = min(ROWNO - 1, ylocale + wander);
            ylocale = rn1(j - i, i);
        }
    }
    /* moved a bit */
    mtmp->mx = COLNO;       /* (already is 0) */
    mtmp->my = xyflags;
    if (xlocale != COLNO)
        mnearto(mtmp, xlocale, ylocale, FALSE);
    else {
        if (!rloc(mtmp, TRUE)) {
            /* Failed to place migrating monster, probably because the level is
               full.  Dump the monster's cargo and leave the monster dead. */
            struct obj *obj;

            while ((obj = mtmp->minvent) != 0) {
                obj_extract_self(obj);
                obj_no_longer_held(obj);
                if (obj->owornmask & W_MASK(os_wep))
                    setmnotwielded(mtmp, obj);
                obj->owornmask = 0L;
                if (xlocale != COLNO && ylocale != ROWNO)
                    place_object(obj, level, xlocale, ylocale);
                else {
                    rloco(obj);
                    get_obj_location(obj, &xlocale, &ylocale, 0);
                }
            }
            mkcorpstat(CORPSE, NULL, mtmp->data, level, xlocale, ylocale,
                       FALSE, rng_main);
            mongone(mtmp);
        }
    }

    mtmp->mux = COLNO;
    mtmp->muy = ROWNO;
}