/** * Allocates a single random object in the dungeon. * \param c the current chunk * \param set where the entity is placed (corridor, room or either) * \param typ what is placed (rubble, trap, gold, item) * \param depth generation depth * \param origin item origin (if appropriate) * * 'set' controls where the object is placed (corridor, room, either). * 'typ' conrols the kind of object (rubble, trap, gold, item). */ bool alloc_object(struct chunk *c, int set, int typ, int depth, byte origin) { int x = 0, y = 0; int tries = 0; /* Pick a "legal" spot */ while (tries < 2000) { tries++; find_empty(c, &y, &x); /* If we are ok with a corridor and we're in one, we're done */ if (set & SET_CORR && !square_isroom(c, y, x)) break; /* If we are ok with a room and we're in one, we're done */ if (set & SET_ROOM && square_isroom(c, y, x)) break; } if (tries == 2000) return false; /* Place something */ switch (typ) { case TYP_RUBBLE: place_rubble(c, y, x); break; case TYP_TRAP: place_trap(c, y, x, -1, depth); break; case TYP_GOLD: place_gold(c, y, x, depth, origin); break; case TYP_OBJECT: place_object(c, y, x, depth, false, false, origin, 0); break; case TYP_GOOD: place_object(c, y, x, depth, true, false, origin, 0); break; case TYP_GREAT: place_object(c, y, x, depth, true, true, origin, 0); break; } return true; }
/* * Aux function -- see below */ static void cave_room_aux(struct point_set *seen, int y, int x) { if (point_set_contains(seen, y, x)) return; if (!square_isroom(cave, y, x)) return; /* Add it to the "seen" set */ add_to_point_set(seen, y, x); }
/** * Choose "logical" directions for monster movement */ static bool get_moves(struct chunk *c, struct monster *mon, int *dir) { int py = player->py; int px = player->px; int y, x; /* Monsters will run up to z_info->flee_range grids out of sight */ int flee_range = z_info->max_sight + z_info->flee_range; bool done = false; /* Calculate range */ find_range(mon); /* Flow towards the player */ if (get_moves_flow(c, mon)) { /* Extract the "pseudo-direction" */ y = mon->ty - mon->fy; x = mon->tx - mon->fx; } else { /* Head straight for the player */ y = player->py - mon->fy; x = player->px - mon->fx; } /* Normal animal packs try to get the player out of corridors. */ if (rf_has(mon->race->flags, RF_GROUP_AI) && !flags_test(mon->race->flags, RF_SIZE, RF_PASS_WALL, RF_KILL_WALL, FLAG_END)) { int i, open = 0; /* Count empty grids next to player */ for (i = 0; i < 8; i++) { int ry = py + ddy_ddd[i]; int rx = px + ddx_ddd[i]; /* Check grid around the player for room interior (room walls count) * or other empty space */ if (square_ispassable(c, ry, rx) || square_isroom(c, ry, rx)) { /* One more open grid */ open++; } } /* Not in an empty space and strong player */ if ((open < 7) && (player->chp > player->mhp / 2)) { /* Find hiding place */ if (find_hiding(c, mon)) { done = true; y = mon->ty - mon->fy; x = mon->tx - mon->fx; } } } /* Apply fear */ if (!done && (mon->min_range == flee_range)) { /* Try to find safe place */ if (!find_safety(c, mon)) { /* Just leg it away from the player */ y = (-y); x = (-x); } else { /* Set a course for the safe place */ get_moves_fear(c, mon); y = mon->ty - mon->fy; x = mon->tx - mon->fx; } done = true; } /* Monster groups try to surround the player */ if (!done && rf_has(mon->race->flags, RF_GROUP_AI)) { int i, yy = mon->ty, xx = mon->tx; /* If we are not already adjacent */ if (mon->cdis > 1) { /* Find an empty square near the player to fill */ int tmp = randint0(8); for (i = 0; i < 8; i++) { /* Pick squares near player (pseudo-randomly) */ yy = py + ddy_ddd[(tmp + i) & 7]; xx = px + ddx_ddd[(tmp + i) & 7]; /* Ignore filled grids */ if (!square_isempty(cave, yy, xx)) continue; /* Try to fill this hole */ break; } } /* Extract the new "pseudo-direction" */ y = yy - mon->fy; x = xx - mon->fx; } /* Check for no move */ if (!x && !y) return (false); /* Pick the correct direction */ *dir = choose_direction(y, x); /* Want to move */ return (true); }
/** * Choose "logical" directions for monster movement */ static bool get_move(struct chunk *c, struct monster *mon, int *dir, bool *good) { struct loc decoy = cave_find_decoy(c); struct loc target = (decoy.y && decoy.x) ? decoy : loc(player->px, player->py); int y, x; /* Monsters will run up to z_info->flee_range grids out of sight */ int flee_range = z_info->max_sight + z_info->flee_range; bool done = false; /* Calculate range */ get_move_find_range(mon); /* Assume we're heading towards the player */ if (get_move_advance(c, mon)) { /* Extract the "pseudo-direction" */ y = mon->target.grid.y - mon->fy; x = mon->target.grid.x - mon->fx; *good = true; } else { /* Head blindly straight for the "player" if there's no better idea */ y = target.y - mon->fy; x = target.x - mon->fx; } /* Normal animal packs try to get the player out of corridors. */ if (rf_has(mon->race->flags, RF_GROUP_AI) && !flags_test(mon->race->flags, RF_SIZE, RF_PASS_WALL, RF_KILL_WALL, FLAG_END)) { int i, open = 0; /* Count empty grids next to player */ for (i = 0; i < 8; i++) { int ry = target.y + ddy_ddd[i]; int rx = target.x + ddx_ddd[i]; /* Check grid around the player for room interior (room walls count) * or other empty space */ if (square_ispassable(c, ry, rx) || square_isroom(c, ry, rx)) { /* One more open grid */ open++; } } /* Not in an empty space and strong player */ if ((open < 5) && (player->chp > player->mhp / 2)) { /* Find hiding place */ if (get_move_find_hiding(c, mon)) { done = true; y = mon->target.grid.y - mon->fy; x = mon->target.grid.x - mon->fx; } } } /* Apply fear */ if (!done && (mon->min_range == flee_range)) { /* Try to find safe place */ if (!get_move_find_safety(c, mon)) { /* Just leg it away from the player */ y = (-y); x = (-x); } else { /* Set a course for the safe place */ get_move_flee(c, mon); y = mon->target.grid.y - mon->fy; x = mon->target.grid.x - mon->fx; } done = true; } /* Monster groups try to surround the player */ if (!done && rf_has(mon->race->flags, RF_GROUP_AI) && square_isview(c, mon->fy, mon->fx)) { int i, yy = mon->target.grid.y, xx = mon->target.grid.x; /* If we are not already adjacent */ if (mon->cdis > 1) { /* Find an empty square near the player to fill */ int tmp = randint0(8); for (i = 0; i < 8; i++) { /* Pick squares near player (pseudo-randomly) */ yy = target.y + ddy_ddd[(tmp + i) & 7]; xx = target.x + ddx_ddd[(tmp + i) & 7]; /* Ignore filled grids */ if (!square_isempty(c, yy, xx)) continue; /* Try to fill this hole */ break; } } /* Extract the new "pseudo-direction" */ y = yy - mon->fy; x = xx - mon->fx; } /* Check if the monster has already reached its target */ if (!x && !y) return (false); /* Pick the correct direction */ *dir = get_move_choose_direction(y, x); /* Want to move */ return (true); }