1 #include "floor/fixed-map-generator.h"
2 #include "artifact/fixed-art-generator.h"
3 #include "dungeon/quest.h"
4 #include "floor/floor-object.h"
5 #include "floor/floor-town.h"
6 #include "floor/wild.h"
7 #include "grid/feature.h"
9 #include "grid/object-placer.h"
10 #include "grid/trap.h"
11 #include "info-reader/general-parser.h"
12 #include "info-reader/random-grid-effect-types.h"
13 #include "io/tokenizer.h"
14 #include "monster-floor/monster-generator.h"
15 #include "monster-floor/place-monster-types.h"
16 #include "monster-race/monster-race.h"
17 #include "monster-race/race-flags1.h"
18 #include "monster-race/race-flags7.h"
19 #include "monster/monster-util.h"
20 #include "monster/smart-learn-types.h"
21 #include "object-enchant/apply-magic.h"
22 #include "object-enchant/item-apply-magic.h"
23 #include "object-enchant/object-ego.h"
24 #include "object-enchant/trg-types.h"
25 #include "object/object-info.h"
26 #include "object/object-kind-hook.h"
27 #include "object/object-kind.h"
28 #include "room/rooms-vault.h"
29 #include "sv-definition/sv-scroll-types.h"
30 #include "system/artifact-type-definition.h"
31 #include "system/floor-type-definition.h"
32 #include "system/grid-type-definition.h"
33 #include "system/monster-race-definition.h"
34 #include "system/monster-type-definition.h"
35 #include "system/player-type-definition.h"
36 #include "window/main-window-util.h"
37 #include "world/world-object.h"
38 #include "world/world.h"
40 // PARSE_ERROR_MAXが既にあり扱い辛いのでここでconst宣言.
41 static const int PARSE_CONTINUE = 255;
43 qtwg_type *initialize_quest_generator_type(qtwg_type *qtwg_ptr, char *buf, int ymin, int xmin, int ymax, int xmax, int *y, int *x)
46 qtwg_ptr->ymin = ymin;
47 qtwg_ptr->xmin = xmin;
48 qtwg_ptr->ymax = ymax;
49 qtwg_ptr->xmax = xmax;
56 * @brief フロアの所定のマスにオブジェクトを配置する
57 * Place the object j_ptr to a grid
58 * @param floor_ptr 現在フロアへの参照ポインタ
59 * @param j_ptr オブジェクト構造体の参照ポインタ
64 static void drop_here(floor_type *floor_ptr, ObjectType *j_ptr, POSITION y, POSITION x)
66 OBJECT_IDX o_idx = o_pop(floor_ptr);
68 o_ptr = &floor_ptr->o_list[o_idx];
69 o_ptr->copy_from(j_ptr);
72 o_ptr->held_m_idx = 0;
73 grid_type *g_ptr = &floor_ptr->grid_array[y][x];
74 g_ptr->o_idx_list.add(floor_ptr, o_idx);
77 static void generate_artifact(PlayerType *player_ptr, qtwg_type *qtwg_ptr, const ARTIFACT_IDX artifact_index)
79 if (artifact_index == 0)
82 if ((a_info[artifact_index].cur_num == 0) && create_named_art(player_ptr, artifact_index, *qtwg_ptr->y, *qtwg_ptr->x)) {
83 a_info[artifact_index].cur_num = 1;
87 KIND_OBJECT_IDX k_idx = lookup_kind(ItemKindType::SCROLL, SV_SCROLL_ACQUIREMENT);
89 ObjectType *q_ptr = &forge;
91 drop_here(player_ptr->current_floor_ptr, q_ptr, *qtwg_ptr->y, *qtwg_ptr->x);
94 static void parse_qtw_D(PlayerType *player_ptr, qtwg_type *qtwg_ptr, char *s)
96 *qtwg_ptr->x = qtwg_ptr->xmin;
97 auto *floor_ptr = player_ptr->current_floor_ptr;
99 for (int i = 0; ((*qtwg_ptr->x < qtwg_ptr->xmax) && (i < len)); (*qtwg_ptr->x)++, s++, i++) {
100 grid_type *g_ptr = &floor_ptr->grid_array[*qtwg_ptr->y][*qtwg_ptr->x];
102 OBJECT_IDX object_index = letter[idx].object;
103 MONSTER_IDX monster_index = letter[idx].monster;
104 int random = letter[idx].random;
105 ARTIFACT_IDX artifact_index = letter[idx].artifact;
106 g_ptr->feat = conv_dungeon_feat(floor_ptr, letter[idx].feature);
107 if (init_flags & INIT_ONLY_FEATURES)
110 g_ptr->info = letter[idx].cave_info;
111 if (random & RANDOM_MONSTER) {
112 floor_ptr->monster_level = floor_ptr->base_level + monster_index;
114 place_monster(player_ptr, *qtwg_ptr->y, *qtwg_ptr->x, (PM_ALLOW_SLEEP | PM_ALLOW_GROUP | PM_NO_QUEST));
116 floor_ptr->monster_level = floor_ptr->base_level;
117 } else if (monster_index) {
118 int old_cur_num, old_max_num;
121 if (monster_index < 0) {
122 monster_index = -monster_index;
126 old_cur_num = r_info[monster_index].cur_num;
127 old_max_num = r_info[monster_index].max_num;
129 if (r_info[monster_index].flags1 & RF1_UNIQUE) {
130 r_info[monster_index].cur_num = 0;
131 r_info[monster_index].max_num = 1;
132 } else if (r_info[monster_index].flags7 & RF7_NAZGUL) {
133 if (r_info[monster_index].cur_num == r_info[monster_index].max_num) {
134 r_info[monster_index].max_num++;
138 place_monster_aux(player_ptr, 0, *qtwg_ptr->y, *qtwg_ptr->x, monster_index, (PM_ALLOW_SLEEP | PM_NO_KAGE));
140 floor_ptr->m_list[hack_m_idx_ii].mflag2.set(MonsterConstantFlagType::CLONED);
141 r_info[monster_index].cur_num = old_cur_num;
142 r_info[monster_index].max_num = old_max_num;
146 if ((random & RANDOM_OBJECT) && (random & RANDOM_TRAP)) {
147 floor_ptr->object_level = floor_ptr->base_level + object_index;
150 * Random trap and random treasure defined
151 * 25% chance for trap and 75% chance for object
153 if (randint0(100) < 75) {
154 place_object(player_ptr, *qtwg_ptr->y, *qtwg_ptr->x, 0L);
156 place_trap(player_ptr, *qtwg_ptr->y, *qtwg_ptr->x);
159 floor_ptr->object_level = floor_ptr->base_level;
160 } else if (random & RANDOM_OBJECT) {
161 floor_ptr->object_level = floor_ptr->base_level + object_index;
162 if (randint0(100) < 75)
163 place_object(player_ptr, *qtwg_ptr->y, *qtwg_ptr->x, 0L);
164 else if (randint0(100) < 80)
165 place_object(player_ptr, *qtwg_ptr->y, *qtwg_ptr->x, AM_GOOD);
167 place_object(player_ptr, *qtwg_ptr->y, *qtwg_ptr->x, AM_GOOD | AM_GREAT);
169 floor_ptr->object_level = floor_ptr->base_level;
170 } else if (random & RANDOM_TRAP) {
171 place_trap(player_ptr, *qtwg_ptr->y, *qtwg_ptr->x);
172 } else if (letter[idx].trap) {
173 g_ptr->mimic = g_ptr->feat;
174 g_ptr->feat = conv_dungeon_feat(floor_ptr, letter[idx].trap);
175 } else if (object_index) {
176 ObjectType tmp_object;
177 ObjectType *o_ptr = &tmp_object;
178 o_ptr->prep(object_index);
179 if (o_ptr->tval == ItemKindType::GOLD) {
180 coin_type = object_index - OBJ_GOLD_LIST;
181 make_gold(player_ptr, o_ptr);
185 apply_magic_to_object(player_ptr, o_ptr, floor_ptr->base_level, AM_NO_FIXED_ART | AM_GOOD);
186 drop_here(floor_ptr, o_ptr, *qtwg_ptr->y, *qtwg_ptr->x);
189 generate_artifact(player_ptr, qtwg_ptr, artifact_index);
190 g_ptr->special = letter[idx].special;
194 static bool parse_qtw_QQ(quest_type *q_ptr, char **zz, int num)
199 if ((init_flags & INIT_ASSIGN) == 0)
203 artifact_type *a_ptr;
208 q_ptr->type = i2enum<QuestKindType>(atoi(zz[2]));
209 q_ptr->num_mon = (MONSTER_NUMBER)atoi(zz[3]);
210 q_ptr->cur_num = (MONSTER_NUMBER)atoi(zz[4]);
211 q_ptr->max_num = (MONSTER_NUMBER)atoi(zz[5]);
212 q_ptr->level = (DEPTH)atoi(zz[6]);
213 q_ptr->r_idx = (MONRACE_IDX)atoi(zz[7]);
214 q_ptr->k_idx = (KIND_OBJECT_IDX)atoi(zz[8]);
215 q_ptr->dungeon = (DUNGEON_IDX)atoi(zz[9]);
218 q_ptr->flags = atoi(zz[10]);
220 r_ptr = &r_info[q_ptr->r_idx];
221 if (r_ptr->flags1 & RF1_UNIQUE)
222 r_ptr->flags1 |= RF1_QUESTOR;
224 a_ptr = &a_info[q_ptr->k_idx];
225 a_ptr->gen_flags.set(ItemGenerationTraitType::QUESTITEM);
230 * @todo 処理がどうなっているのかいずれチェックする
232 static bool parse_qtw_QR(quest_type *q_ptr, char **zz, int num)
237 if ((init_flags & INIT_ASSIGN) == 0)
241 ARTIFACT_IDX idx, reward_idx = 0;
242 for (idx = 2; idx < num; idx++) {
243 ARTIFACT_IDX a_idx = (ARTIFACT_IDX)atoi(zz[idx]);
246 if (a_info[a_idx].cur_num > 0)
254 q_ptr->k_idx = (KIND_OBJECT_IDX)reward_idx;
255 a_info[reward_idx].gen_flags.set(ItemGenerationTraitType::QUESTITEM);
257 q_ptr->type = QuestKindType::KILL_ALL;
264 * @brief t_info、q_info、w_infoにおけるQトークンをパースする
265 * @param qtwg_ptr トークンパース構造体への参照ポインタ
266 * @param zz トークン保管文字列
267 * @return エラーコード、但しPARSE_CONTINUEの時は処理続行
269 static int parse_qtw_Q(qtwg_type *qtwg_ptr, char **zz)
271 if (qtwg_ptr->buf[0] != 'Q')
272 return PARSE_CONTINUE;
275 if (qtwg_ptr->buf[2] == '$')
276 return PARSE_ERROR_NONE;
278 if (qtwg_ptr->buf[2] != '$')
279 return PARSE_ERROR_NONE;
282 int num = tokenize(qtwg_ptr->buf + _(2, 3), 33, zz, 0);
284 return PARSE_ERROR_TOO_FEW_ARGUMENTS;
287 q_ptr = &(quest[atoi(zz[0])]);
288 if (parse_qtw_QQ(q_ptr, zz, num))
289 return PARSE_ERROR_NONE;
291 if (parse_qtw_QR(q_ptr, zz, num))
292 return PARSE_ERROR_NONE;
294 if (zz[1][0] == 'N') {
295 if (init_flags & (INIT_ASSIGN | INIT_SHOW_TEXT | INIT_NAME_ONLY)) {
296 strcpy(q_ptr->name, zz[2]);
299 return PARSE_ERROR_NONE;
302 if (zz[1][0] == 'T') {
303 if (init_flags & INIT_SHOW_TEXT) {
304 strcpy(quest_text[quest_text_line], zz[2]);
308 return PARSE_ERROR_NONE;
311 return PARSE_ERROR_GENERIC;
314 static bool parse_qtw_P(PlayerType *player_ptr, qtwg_type *qtwg_ptr, char **zz)
316 if (qtwg_ptr->buf[0] != 'P')
319 if ((init_flags & INIT_CREATE_DUNGEON) == 0)
322 if (tokenize(qtwg_ptr->buf + 2, 2, zz, 0) != 2)
325 int panels_y = (*qtwg_ptr->y / SCREEN_HGT);
326 if (*qtwg_ptr->y % SCREEN_HGT)
329 auto *floor_ptr = player_ptr->current_floor_ptr;
330 floor_ptr->height = panels_y * SCREEN_HGT;
331 int panels_x = (*qtwg_ptr->x / SCREEN_WID);
332 if (*qtwg_ptr->x % SCREEN_WID)
335 floor_ptr->width = panels_x * SCREEN_WID;
336 panel_row_min = floor_ptr->height;
337 panel_col_min = floor_ptr->width;
338 if (inside_quest(floor_ptr->quest_number)) {
339 POSITION py = atoi(zz[0]);
340 POSITION px = atoi(zz[1]);
343 delete_monster(player_ptr, player_ptr->y, player_ptr->x);
347 if (!player_ptr->oldpx && !player_ptr->oldpy) {
348 player_ptr->oldpy = atoi(zz[0]);
349 player_ptr->oldpx = atoi(zz[1]);
355 static bool parse_qtw_M(qtwg_type *qtwg_ptr, char **zz)
357 if (qtwg_ptr->buf[0] != 'M')
360 if ((tokenize(qtwg_ptr->buf + 2, 2, zz, 0) == 2) == 0)
363 if (zz[0][0] == 'T') {
364 max_towns = static_cast<int16_t>(atoi(zz[1]));
365 } else if (zz[0][0] == 'Q') {
366 max_q_idx = (int16_t)atoi(zz[1]);
367 } else if (zz[0][0] == 'O') {
368 w_ptr->max_o_idx = (OBJECT_IDX)atoi(zz[1]);
369 } else if (zz[0][0] == 'M') {
370 w_ptr->max_m_idx = (MONSTER_IDX)atoi(zz[1]);
371 } else if (zz[0][0] == 'W') {
373 w_ptr->max_wild_x = (POSITION)atoi(zz[1]);
376 w_ptr->max_wild_y = (POSITION)atoi(zz[1]);
383 * @brief 固定マップ (クエスト&街&広域マップ)をフロアに生成する
384 * Parse a sub-file of the "extra info"
385 * @param player_ptr プレイヤーへの参照ポインタ
394 * @todo クエスト情報のみを読み込む手段と実際にフロアデータまで読み込む処理は分離したい
396 parse_error_type generate_fixed_map_floor(PlayerType *player_ptr, qtwg_type *qtwg_ptr, process_dungeon_file_pf parse_fixed_map)
399 if (!qtwg_ptr->buf[0])
400 return PARSE_ERROR_NONE;
402 if (iswspace(qtwg_ptr->buf[0]))
403 return PARSE_ERROR_NONE;
405 if (qtwg_ptr->buf[0] == '#')
406 return PARSE_ERROR_NONE;
408 if (qtwg_ptr->buf[1] != ':')
409 return PARSE_ERROR_GENERIC;
411 if (qtwg_ptr->buf[0] == '%')
412 return (*parse_fixed_map)(player_ptr, qtwg_ptr->buf + 2, qtwg_ptr->ymin, qtwg_ptr->xmin, qtwg_ptr->ymax, qtwg_ptr->xmax);
414 /* Process "F:<letter>:<terrain>:<cave_info>:<monster>:<object>:<ego>:<artifact>:<trap>:<special>" -- info for dungeon grid */
415 if (qtwg_ptr->buf[0] == 'F')
416 return parse_line_feature(player_ptr->current_floor_ptr, qtwg_ptr->buf);
418 if (qtwg_ptr->buf[0] == 'D') {
419 char *s = qtwg_ptr->buf + 2;
420 if (init_flags & INIT_ONLY_BUILDINGS)
421 return PARSE_ERROR_NONE;
423 parse_qtw_D(player_ptr, qtwg_ptr, s);
425 return PARSE_ERROR_NONE;
428 parse_error_type parse_result_Q = i2enum<parse_error_type>(parse_qtw_Q(qtwg_ptr, zz));
429 if (parse_result_Q != PARSE_CONTINUE)
430 return parse_result_Q;
432 if (qtwg_ptr->buf[0] == 'W')
433 return parse_line_wilderness(player_ptr, qtwg_ptr->buf, qtwg_ptr->xmin, qtwg_ptr->xmax, qtwg_ptr->y, qtwg_ptr->x);
435 if (parse_qtw_P(player_ptr, qtwg_ptr, zz))
436 return PARSE_ERROR_NONE;
438 if (qtwg_ptr->buf[0] == 'B')
439 return parse_line_building(qtwg_ptr->buf);
441 if (parse_qtw_M(qtwg_ptr, zz))
442 return PARSE_ERROR_NONE;
444 return PARSE_ERROR_GENERIC;