2 * @brief フロア全体の処理に関するユーティリティ
6 #include "floor/floor-util.h"
7 #include "dungeon/dungeon.h"
8 #include "dungeon/quest.h"
9 #include "effect/effect-characteristics.h"
10 #include "floor/cave.h"
11 #include "floor/floor-object.h"
12 #include "floor/floor-town.h"
13 #include "floor/geometry.h"
14 #include "floor/line-of-sight.h"
15 #include "game-option/birth-options.h"
16 #include "grid/feature.h"
17 #include "object-hook/hook-checker.h"
18 #include "object-hook/hook-enchant.h"
19 #include "perception/object-perception.h"
20 #include "system/artifact-type-definition.h"
21 #include "system/floor-type-definition.h"
22 #include "system/grid-type-definition.h"
23 #include "system/monster-type-definition.h"
24 #include "system/player-type-definition.h"
25 #include "target/projection-path-calculator.h"
26 #include "world/world.h"
29 * The array of floor [MAX_WID][MAX_HGT].
30 * Not completely allocated, that would be inefficient
31 * Not completely hardcoded, that would overflow memory
33 floor_type floor_info;
35 static int scent_when = 0;
38 * Characters leave scent trails for perceptive monsters to track.
40 * Smell is rather more limited than sound. Many creatures cannot use
41 * it at all, it doesn't extend very far outwards from the character's
42 * current position, and monsters can use it to home in the character,
43 * but not to run away from him.
45 * Smell is valued according to age. When a character takes his turn,
46 * scent is aged by one, and new scent of the current age is laid down.
47 * Speedy characters leave more scent, true, but it also ages faster,
48 * which makes it harder to hunt them down.
50 * Whenever the age count loops, most of the scent trail is erased and
51 * the age of the remainder is recalculated.
53 void update_smell(floor_type *floor_ptr, player_type *subject_ptr)
55 /* Create a table that controls the spread of scent */
56 const int scent_adjust[5][5] = {
64 if (++scent_when == 254) {
65 for (POSITION y = 0; y < floor_ptr->height; y++) {
66 for (POSITION x = 0; x < floor_ptr->width; x++) {
67 int w = floor_ptr->grid_array[y][x].when;
68 floor_ptr->grid_array[y][x].when = (w > 128) ? (w - 128) : 0;
75 for (POSITION i = 0; i < 5; i++) {
76 for (POSITION j = 0; j < 5; j++) {
78 POSITION y = i + subject_ptr->y - 2;
79 POSITION x = j + subject_ptr->x - 2;
80 if (!in_bounds(floor_ptr, y, x))
83 g_ptr = &floor_ptr->grid_array[y][x];
84 if (!cave_has_flag_grid(g_ptr, FF_MOVE) && !is_closed_door(subject_ptr, g_ptr->feat))
86 if (!player_has_los_bold(subject_ptr, y, x))
88 if (scent_adjust[i][j] == -1)
91 g_ptr->when = scent_when + scent_adjust[i][j];
97 * Hack -- forget the "flow" information
99 void forget_flow(floor_type *floor_ptr)
101 for (POSITION y = 0; y < floor_ptr->height; y++) {
102 for (POSITION x = 0; x < floor_ptr->width; x++) {
103 memset(&floor_ptr->grid_array[y][x].costs, 0, sizeof(floor_ptr->grid_array[y][x].costs));
104 memset(&floor_ptr->grid_array[y][x].dists, 0, sizeof(floor_ptr->grid_array[y][x].dists));
105 floor_ptr->grid_array[y][x].when = 0;
111 * @brief グローバルオブジェクト配列を初期化する /
112 * Delete all the items when player leaves the level
113 * @note we do NOT visually reflect these (irrelevant) changes
115 * Hack -- we clear the "g_ptr->o_idx" field for every grid,
116 * and the "m_ptr->next_o_idx" field for every monster, since
117 * we know we are clearing every object. Technically, we only
118 * clear those fields for grids/monsters containing objects,
119 * and we clear it once for every such object.
121 void wipe_o_list(floor_type *floor_ptr)
123 for (OBJECT_IDX i = 1; i < floor_ptr->o_max; i++) {
124 object_type *o_ptr = &floor_ptr->o_list[i];
125 if (!object_is_valid(o_ptr))
128 if (!current_world_ptr->character_dungeon || preserve_mode) {
129 if (object_is_fixed_artifact(o_ptr) && !object_is_known(o_ptr)) {
130 a_info[o_ptr->name1].cur_num = 0;
134 auto &list = get_o_idx_list_contains(floor_ptr, i);
139 floor_ptr->o_max = 1;
140 floor_ptr->o_cnt = 0;
144 * Standard "find me a location" function
146 * Obtains a legal location within the given distance of the initial
147 * location, and with "los()" from the source to destination location.
149 * This function is often called from inside a loop which searches for
150 * locations while increasing the "d" distance.
152 * Currently the "m" parameter is unused.
154 void scatter(player_type *player_ptr, POSITION *yp, POSITION *xp, POSITION y, POSITION x, POSITION d, BIT_FLAGS mode)
156 floor_type *floor_ptr = player_ptr->current_floor_ptr;
159 ny = rand_spread(y, d);
160 nx = rand_spread(x, d);
162 if (!in_bounds(floor_ptr, ny, nx))
164 if ((d > 1) && (distance(y, x, ny, nx) > d))
166 if (mode & PROJECT_LOS) {
167 if (los(player_ptr, y, x, ny, nx))
172 if (projectable(player_ptr, y, x, ny, nx))
181 * @brief 現在のマップ名を返す /
182 * @param creature_ptr プレーヤーへの参照ポインタ
183 * @return マップ名の文字列参照ポインタ
185 concptr map_name(player_type *creature_ptr)
187 floor_type *floor_ptr = creature_ptr->current_floor_ptr;
188 if (floor_ptr->inside_quest && is_fixed_quest_idx(floor_ptr->inside_quest) && (quest[floor_ptr->inside_quest].flags & QUEST_FLAG_PRESET))
189 return _("クエスト", "Quest");
190 else if (creature_ptr->wild_mode)
191 return _("地上", "Surface");
192 else if (floor_ptr->inside_arena)
193 return _("アリーナ", "Arena");
194 else if (creature_ptr->phase_out)
195 return _("闘技場", "Monster Arena");
196 else if (!floor_ptr->dun_level && creature_ptr->town_num)
197 return town_info[creature_ptr->town_num].name;
199 return d_info[creature_ptr->dungeon_idx].name.c_str();