Beispiel #1
0
/**
 * Try to push past / kill another monster.  Returns true on success.
 */
static bool process_monster_try_push(struct chunk *c, struct monster *mon,
									 const char *m_name, int nx, int ny)
{
	struct monster *mon1 = square_monster(c, ny, nx);
	struct monster_lore *lore = get_lore(mon->race);

	/* Kill weaker monsters */
	int kill_ok = rf_has(mon->race->flags, RF_KILL_BODY);

	/* Move weaker monsters if they can swap places */
	/* (not in a wall) */
	int move_ok = (rf_has(mon->race->flags, RF_MOVE_BODY) &&
				   square_ispassable(c, mon->fy, mon->fx));

	if (compare_monsters(mon, mon1) > 0) {
		/* Learn about pushing and shoving */
		if (mflag_has(mon->mflag, MFLAG_VISIBLE)) {
			rf_on(lore->flags, RF_KILL_BODY);
			rf_on(lore->flags, RF_MOVE_BODY);
		}

		if (kill_ok || move_ok) {
			/* Get the names of the monsters involved */
			char n_name[80];
			monster_desc(n_name, sizeof(n_name), mon1, MDESC_IND_HID);

			/* Reveal mimics */
			if (is_mimicking(mon1))
				become_aware(mon1);

			/* Note if visible */
			if (mflag_has(mon->mflag, MFLAG_VISIBLE) &&
				mflag_has(mon->mflag, MFLAG_VIEW))
				msg("%s %s %s.", m_name,
					kill_ok ? "tramples over" : "pushes past", n_name);

			/* Monster ate another monster */
			if (kill_ok)
				delete_monster(ny, nx);

			monster_swap(mon->fy, mon->fx, ny, nx);
			return true;
		} 
	}

	return false;
}
Beispiel #2
0
/*
 * Place a random type of door at the given location
 */
void place_random_door(int y, int x, bool room)
{
    int tmp, type;
    s16b feat = feat_none;
    cave_type *c_ptr = &cave[y][x];

    /* Initialize mimic info */
    c_ptr->mimic = 0;

/*    if (dungeon_type == DUNGEON_ARENA)
    {
        place_rubble_bold(y, x);
        return;
    }*/

    if (d_info[dungeon_type].flags1 & DF1_NO_DOORS)
    {
        place_floor_bold(y, x);
        return;
    }

    type = ((d_info[dungeon_type].flags1 & DF1_CURTAIN) &&
        one_in_((d_info[dungeon_type].flags1 & DF1_NO_CAVE) ? 16 : 256)) ? DOOR_CURTAIN :
        ((d_info[dungeon_type].flags1 & DF1_GLASS_DOOR) ? DOOR_GLASS_DOOR : DOOR_DOOR);

    /* Choose an object */
    tmp = randint0(1000);

    /* Open doors (300/1000) */
    if (tmp < 300)
    {
        /* Create open door */
        feat = feat_door[type].open;
    }

    /* Broken doors (100/1000) */
    else if (tmp < 400)
    {
        /* Create broken door */
        feat = feat_door[type].broken;
    }

    /* Secret doors (200/1000) */
    else if (tmp < 600)
    {
        /* Create secret door */
        place_closed_door(y, x, type);

        if (type != DOOR_CURTAIN)
        {
            /* Hide. If on the edge of room, use outer wall. */
            c_ptr->mimic = room ? feat_wall_outer : fill_type[randint0(100)];

            /* Floor type terrain cannot hide a door */
            if (feat_supports_los(c_ptr->mimic) && !feat_supports_los(c_ptr->feat))
            {
                if (have_flag(f_info[c_ptr->mimic].flags, FF_MOVE) || have_flag(f_info[c_ptr->mimic].flags, FF_CAN_FLY))
                {
                    c_ptr->feat = one_in_(2) ? c_ptr->mimic : floor_type[randint0(100)];
                }
                c_ptr->mimic = 0;
            }
        }
    }

    /* Closed, locked, or stuck doors (400/1000) */
    else place_closed_door(y, x, type);

    if (tmp < 400)
    {
        if (feat != feat_none)
        {
            set_cave_feat(y, x, feat);
        }
        else
        {
            place_floor_bold(y, x);
        }
    }

    delete_monster(y, x);
}
Beispiel #3
0
/**
 * Compacts and reorders the monster list.
 *
 * This function can be very dangerous, use with caution!
 *
 * When `num_to_compact` is 0, we just reorder the monsters into a more compact
 * order, eliminating any "holes" left by dead monsters. If `num_to_compact` is
 * positive, then we delete at least that many monsters and then reorder.
 * We try not to delete monsters that are high level or close to the player.
 * Each time we make a full pass through the monster list, if we haven't
 * deleted enough monsters, we relax our bounds a little to accept
 * monsters of a slightly higher level, and monsters slightly closer to
 * the player.
 */
void compact_monsters(int num_to_compact)
{
	int m_idx, num_compacted, iter;

	int max_lev, min_dis, chance;


	/* Message (only if compacting) */
	if (num_to_compact)
		msg("Compacting monsters...");


	/* Compact at least 'num_to_compact' objects */
	for (num_compacted = 0, iter = 1; num_compacted < num_to_compact; iter++) {
		/* Get more vicious each iteration */
		max_lev = 5 * iter;

		/* Get closer each iteration */
		min_dis = 5 * (20 - iter);

		/* Check all the monsters */
		for (m_idx = 1; m_idx < cave_monster_max(cave); m_idx++) {
			struct monster *mon = cave_monster(cave, m_idx);

			/* Skip "dead" monsters */
			if (!mon->race) continue;

			/* High level monsters start out "immune" */
			if (mon->race->level > max_lev) continue;

			/* Ignore nearby monsters */
			if ((min_dis > 0) && (mon->cdis < min_dis)) continue;

			/* Saving throw chance */
			chance = 90;

			/* Only compact "Quest" Monsters in emergencies */
			if (rf_has(mon->race->flags, RF_QUESTOR) && (iter < 1000))
				chance = 100;

			/* Try not to compact Unique Monsters */
			if (rf_has(mon->race->flags, RF_UNIQUE)) chance = 99;

			/* All monsters get a saving throw */
			if (randint0(100) < chance) continue;

			/* Delete the monster */
			delete_monster(mon->fy, mon->fx);

			/* Count the monster */
			num_compacted++;
		}
	}


	/* Excise dead monsters (backwards!) */
	for (m_idx = cave_monster_max(cave) - 1; m_idx >= 1; m_idx--) {
		struct monster *mon = cave_monster(cave, m_idx);

		/* Skip real monsters */
		if (mon->race) continue;

		/* Move last monster into open hole */
		compact_monsters_aux(cave_monster_max(cave) - 1, m_idx);

		/* Compress "cave->mon_max" */
		cave->mon_max--;
	}
}
/*
 * Places "streamers" of rock through dungeon
 *
 * Note that their are actually six different terrain features used
 * to represent streamers.  Three each of magma and quartz, one for
 * basic vein, one with hidden gold, and one with known gold.  The
 * hidden gold types are currently unused.
 */
void build_streamer(int feat, int chance)
{
    int        i, tx, ty;
    int        y, x, dir;
    int dummy = 0;

    cave_type *c_ptr;
    feature_type *f_ptr;

    feature_type *streamer_ptr = &f_info[feat];
    bool streamer_is_wall = have_flag(streamer_ptr->flags, FF_WALL) && !have_flag(streamer_ptr->flags, FF_PERMANENT);
    bool streamer_may_have_gold = have_flag(streamer_ptr->flags, FF_MAY_HAVE_GOLD);

    /* Hack -- Choose starting point */
    y = rand_spread(cur_hgt / 2, cur_hgt / 6);
    x = rand_spread(cur_wid / 2, cur_wid / 6);

    /* Choose a random compass direction */
    dir = ddd[randint0(8)];

    /* Place streamer into dungeon */
    while (dummy < SAFE_MAX_ATTEMPTS)
    {
        dummy++;

        /* One grid per density */
        for (i = 0; i < DUN_STR_DEN; i++)
        {
            int d = DUN_STR_RNG;

            /* Pick a nearby grid */
            while (1)
            {
                ty = rand_spread(y, d);
                tx = rand_spread(x, d);
                if (!in_bounds2(ty, tx)) continue;
                break;
            }

            /* Access the grid */
            c_ptr = &cave[ty][tx];
            f_ptr = &f_info[c_ptr->feat];

            if (have_flag(f_ptr->flags, FF_MOVE) && (have_flag(f_ptr->flags, FF_WATER) || have_flag(f_ptr->flags, FF_LAVA)))
                continue;

            /* Do not convert permanent features */
            if (have_flag(f_ptr->flags, FF_PERMANENT)) continue;

            /* Only convert "granite" walls */
            if (streamer_is_wall)
            {
                if (!is_extra_grid(c_ptr) && !is_inner_grid(c_ptr) && !is_outer_grid(c_ptr) && !is_solid_grid(c_ptr)) continue;
                if (is_closed_door(c_ptr->feat)) continue;
            }

            if (c_ptr->m_idx && !(have_flag(streamer_ptr->flags, FF_PLACE) && monster_can_cross_terrain(feat, &r_info[m_list[c_ptr->m_idx].r_idx], 0)))
            {
                /* Delete the monster (if any) */
                delete_monster(ty, tx);
            }

            if (c_ptr->o_idx && !have_flag(streamer_ptr->flags, FF_DROP))
            {
                s16b this_o_idx, next_o_idx = 0;

                /* Scan all objects in the grid */
                for (this_o_idx = c_ptr->o_idx; this_o_idx; this_o_idx = next_o_idx)
                {
                    /* Acquire object */
                    object_type *o_ptr = &o_list[this_o_idx];

                    /* Acquire next object */
                    next_o_idx = o_ptr->next_o_idx;

                    /* Hack -- Preserve unknown artifacts */
                    if (object_is_fixed_artifact(o_ptr))
                    {
                        /* Mega-Hack -- Preserve the artifact */
                        a_info[o_ptr->name1].cur_num = 0;

                        if (cheat_peek)
                        {
                            char o_name[MAX_NLEN];
                            object_desc(o_name, o_ptr, (OD_NAME_ONLY | OD_STORE));
                            msg_format("Artifact (%s) was deleted by streamer.", o_name);
                        }
                    }
                    else if (o_ptr->name3)
                    {
                        /* Mega-Hack -- Preserve the artifact */
                        a_info[o_ptr->name3].cur_num = 0;

                        if (cheat_peek)
                        {
                            char o_name[MAX_NLEN];
                            object_desc(o_name, o_ptr, (OD_NAME_ONLY | OD_STORE));
                            msg_format("Artifact (%s) was deleted by streamer.", o_name);
                        }
                    }
                    else if (cheat_peek && o_ptr->art_name)
                    {
                        msg_print("One of the random artifacts was deleted by streamer.");
                    }
                }

                /* Delete objects */
                delete_object(ty, tx);
            }

            /* Clear previous contents, add proper vein type */
            c_ptr->feat = feat;

            /* Paranoia: Clear mimic field */
            c_ptr->mimic = 0;

            if (streamer_may_have_gold)
            {
                /* Hack -- Add some known treasure */
                if (one_in_(chance))
                {
                    cave_alter_feat(ty, tx, FF_MAY_HAVE_GOLD);
                }

                /* Hack -- Add some hidden treasure */
                else if (one_in_(chance / 4))
                {
                    cave_alter_feat(ty, tx, FF_MAY_HAVE_GOLD);
                    cave_alter_feat(ty, tx, FF_ENSECRET);
                }
            }
        }

        if (dummy >= SAFE_MAX_ATTEMPTS)
        {
            if (cheat_room)
            {
                msg_print("Warning! Could not place streamer!");

            }
            return;
        }


        /* Advance the streamer */
        y += ddy[dir];
        x += ddx[dir];

        /* Quit before leaving the dungeon */
        if (!in_bounds(y, x)) break;
    }
}