OSDN Git Service

Merge pull request #489 from iks3/feature-gen-flags-to-flaggroup
[hengbandforosx/hengbandosx.git] / src / floor / fixed-map-generator.cpp
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"
8 #include "grid/grid.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-generator.h"
26 #include "object/object-info.h"
27 #include "object/object-kind-hook.h"
28 #include "object/object-kind.h"
29 #include "room/rooms-vault.h"
30 #include "sv-definition/sv-scroll-types.h"
31 #include "system/artifact-type-definition.h"
32 #include "system/floor-type-definition.h"
33 #include "system/system-variables.h"
34 #include "window/main-window-util.h"
35 #include "world/world-object.h"
36 #include "world/world.h"
37
38 // PARSE_ERROR_MAXが既にあり扱い辛いのでここでconst宣言.
39 static const int PARSE_CONTINUE = 255;
40
41 qtwg_type *initialize_quest_generator_type(qtwg_type *qtwg_ptr, char *buf, int ymin, int xmin, int ymax, int xmax, int *y, int *x)
42 {
43     qtwg_ptr->buf = buf;
44     qtwg_ptr->ymin = ymin;
45     qtwg_ptr->xmin = xmin;
46     qtwg_ptr->ymax = ymax;
47     qtwg_ptr->xmax = xmax;
48     qtwg_ptr->y = y;
49     qtwg_ptr->x = x;
50     return qtwg_ptr;
51 }
52
53 /*!
54  * @brief フロアの所定のマスにオブジェクトを配置する
55  * Place the object j_ptr to a grid
56  * @param floor_ptr 現在フロアへの参照ポインタ
57  * @param j_ptr オブジェクト構造体の参照ポインタ
58  * @param y 配置先Y座標
59  * @param x 配置先X座標
60  * @return エラーコード
61  */
62 static void drop_here(floor_type *floor_ptr, object_type *j_ptr, POSITION y, POSITION x)
63 {
64     OBJECT_IDX o_idx = o_pop(floor_ptr);
65     object_type *o_ptr;
66     o_ptr = &floor_ptr->o_list[o_idx];
67     object_copy(o_ptr, j_ptr);
68     o_ptr->iy = y;
69     o_ptr->ix = x;
70     o_ptr->held_m_idx = 0;
71     grid_type *g_ptr = &floor_ptr->grid_array[y][x];
72     o_ptr->next_o_idx = g_ptr->o_idx;
73     g_ptr->o_idx = o_idx;
74 }
75
76 static void generate_artifact(player_type *player_ptr, qtwg_type *qtwg_ptr, const ARTIFACT_IDX artifact_index)
77 {
78     if (artifact_index == 0)
79         return;
80
81     if ((a_info[artifact_index].cur_num == 0) && create_named_art(player_ptr, artifact_index, *qtwg_ptr->y, *qtwg_ptr->x)) {
82         a_info[artifact_index].cur_num = 1;
83         return;
84     }
85
86     KIND_OBJECT_IDX k_idx = lookup_kind(TV_SCROLL, SV_SCROLL_ACQUIREMENT);
87     object_type forge;
88     object_type *q_ptr = &forge;
89     object_prep(player_ptr, q_ptr, k_idx);
90     drop_here(player_ptr->current_floor_ptr, q_ptr, *qtwg_ptr->y, *qtwg_ptr->x);
91 }
92
93 static void parse_qtw_D(player_type *player_ptr, qtwg_type *qtwg_ptr, char *s)
94 {
95     *qtwg_ptr->x = qtwg_ptr->xmin;
96     floor_type *floor_ptr = player_ptr->current_floor_ptr;
97     int len = strlen(s);
98     for (int i = 0; ((*qtwg_ptr->x < qtwg_ptr->xmax) && (i < len)); (*qtwg_ptr->x)++, s++, i++) {
99         grid_type *g_ptr = &floor_ptr->grid_array[*qtwg_ptr->y][*qtwg_ptr->x];
100         int idx = s[0];
101         OBJECT_IDX object_index = letter[idx].object;
102         MONSTER_IDX monster_index = letter[idx].monster;
103         int random = letter[idx].random;
104         ARTIFACT_IDX artifact_index = letter[idx].artifact;
105         g_ptr->feat = conv_dungeon_feat(floor_ptr, letter[idx].feature);
106         if (init_flags & INIT_ONLY_FEATURES)
107             continue;
108
109         g_ptr->info = letter[idx].cave_info;
110         if (random & RANDOM_MONSTER) {
111             floor_ptr->monster_level = floor_ptr->base_level + monster_index;
112
113             place_monster(player_ptr, *qtwg_ptr->y, *qtwg_ptr->x, (PM_ALLOW_SLEEP | PM_ALLOW_GROUP));
114
115             floor_ptr->monster_level = floor_ptr->base_level;
116         } else if (monster_index) {
117             int old_cur_num, old_max_num;
118             bool clone = FALSE;
119
120             if (monster_index < 0) {
121                 monster_index = -monster_index;
122                 clone = TRUE;
123             }
124
125             old_cur_num = r_info[monster_index].cur_num;
126             old_max_num = r_info[monster_index].max_num;
127
128             if (r_info[monster_index].flags1 & RF1_UNIQUE) {
129                 r_info[monster_index].cur_num = 0;
130                 r_info[monster_index].max_num = 1;
131             } else if (r_info[monster_index].flags7 & RF7_NAZGUL) {
132                 if (r_info[monster_index].cur_num == r_info[monster_index].max_num) {
133                     r_info[monster_index].max_num++;
134                 }
135             }
136
137             place_monster_aux(player_ptr, 0, *qtwg_ptr->y, *qtwg_ptr->x, monster_index, (PM_ALLOW_SLEEP | PM_NO_KAGE));
138             if (clone) {
139                 floor_ptr->m_list[hack_m_idx_ii].smart |= SM_CLONED;
140                 r_info[monster_index].cur_num = old_cur_num;
141                 r_info[monster_index].max_num = old_max_num;
142             }
143         }
144
145         if ((random & RANDOM_OBJECT) && (random & RANDOM_TRAP)) {
146             floor_ptr->object_level = floor_ptr->base_level + object_index;
147
148             /*
149              * Random trap and random treasure defined
150              * 25% chance for trap and 75% chance for object
151              */
152             if (randint0(100) < 75) {
153                 place_object(player_ptr, *qtwg_ptr->y, *qtwg_ptr->x, 0L);
154             } else {
155                 place_trap(player_ptr, *qtwg_ptr->y, *qtwg_ptr->x);
156             }
157
158             floor_ptr->object_level = floor_ptr->base_level;
159         } else if (random & RANDOM_OBJECT) {
160             floor_ptr->object_level = floor_ptr->base_level + object_index;
161             if (randint0(100) < 75)
162                 place_object(player_ptr, *qtwg_ptr->y, *qtwg_ptr->x, 0L);
163             else if (randint0(100) < 80)
164                 place_object(player_ptr, *qtwg_ptr->y, *qtwg_ptr->x, AM_GOOD);
165             else
166                 place_object(player_ptr, *qtwg_ptr->y, *qtwg_ptr->x, AM_GOOD | AM_GREAT);
167
168             floor_ptr->object_level = floor_ptr->base_level;
169         } else if (random & RANDOM_TRAP) {
170             place_trap(player_ptr, *qtwg_ptr->y, *qtwg_ptr->x);
171         } else if (letter[idx].trap) {
172             g_ptr->mimic = g_ptr->feat;
173             g_ptr->feat = conv_dungeon_feat(floor_ptr, letter[idx].trap);
174         } else if (object_index) {
175             object_type tmp_object;
176             object_type *o_ptr = &tmp_object;
177             object_prep(player_ptr, o_ptr, object_index);
178             if (o_ptr->tval == TV_GOLD) {
179                 coin_type = object_index - OBJ_GOLD_LIST;
180                 make_gold(player_ptr, o_ptr);
181                 coin_type = 0;
182             }
183
184             apply_magic(player_ptr, o_ptr, floor_ptr->base_level, AM_NO_FIXED_ART | AM_GOOD);
185             drop_here(floor_ptr, o_ptr, *qtwg_ptr->y, *qtwg_ptr->x);
186         }
187
188         generate_artifact(player_ptr, qtwg_ptr, artifact_index);
189         g_ptr->special = letter[idx].special;
190     }
191 }
192
193 static bool parse_qtw_QQ(quest_type *q_ptr, char **zz, int num)
194 {
195     if (zz[1][0] != 'Q')
196         return FALSE;
197
198     if ((init_flags & INIT_ASSIGN) == 0)
199         return TRUE;
200
201     monster_race *r_ptr;
202     artifact_type *a_ptr;
203
204     if (num < 9)
205         return TRUE;
206
207     q_ptr->type = (QUEST_TYPE)atoi(zz[2]);
208     q_ptr->num_mon = (MONSTER_NUMBER)atoi(zz[3]);
209     q_ptr->cur_num = (MONSTER_NUMBER)atoi(zz[4]);
210     q_ptr->max_num = (MONSTER_NUMBER)atoi(zz[5]);
211     q_ptr->level = (DEPTH)atoi(zz[6]);
212     q_ptr->r_idx = (MONRACE_IDX)atoi(zz[7]);
213     q_ptr->k_idx = (KIND_OBJECT_IDX)atoi(zz[8]);
214     q_ptr->dungeon = (DUNGEON_IDX)atoi(zz[9]);
215
216     if (num > 10)
217         q_ptr->flags = atoi(zz[10]);
218
219     r_ptr = &r_info[q_ptr->r_idx];
220     if (r_ptr->flags1 & RF1_UNIQUE)
221         r_ptr->flags1 |= RF1_QUESTOR;
222
223     a_ptr = &a_info[q_ptr->k_idx];
224     a_ptr->gen_flags.set(TRG::QUESTITEM);
225     return TRUE;
226 }
227
228 /**
229  * @todo 処理がどうなっているのかいずれチェックする
230  */
231 static bool parse_qtw_QR(quest_type *q_ptr, char **zz, int num)
232 {
233     if (zz[1][0] != 'R')
234         return FALSE;
235
236     if ((init_flags & INIT_ASSIGN) == 0)
237         return TRUE;
238
239     int count = 0;
240     ARTIFACT_IDX idx, reward_idx = 0;
241     for (idx = 2; idx < num; idx++) {
242         ARTIFACT_IDX a_idx = (ARTIFACT_IDX)atoi(zz[idx]);
243         if (a_idx < 1)
244             continue;
245         if (a_info[a_idx].cur_num > 0)
246             continue;
247         count++;
248         if (one_in_(count))
249             reward_idx = a_idx;
250     }
251
252     if (reward_idx) {
253         q_ptr->k_idx = (KIND_OBJECT_IDX)reward_idx;
254         a_info[reward_idx].gen_flags.set(TRG::QUESTITEM);
255     } else {
256         q_ptr->type = QUEST_TYPE_KILL_ALL;
257     }
258
259     return TRUE;
260 }
261
262 /*!
263  * @brief t_info、q_info、w_infoにおけるQトークンをパースする
264  * @param qtwg_ptr トークンパース構造体への参照ポインタ
265  * @param zz トークン保管文字列
266  * @return エラーコード、但しPARSE_CONTINUEの時は処理続行
267  */
268 static int parse_qtw_Q(qtwg_type *qtwg_ptr, char **zz)
269 {
270     if (qtwg_ptr->buf[0] != 'Q')
271         return PARSE_CONTINUE;
272
273 #ifdef JP
274     if (qtwg_ptr->buf[2] == '$')
275         return PARSE_ERROR_NONE;
276 #else
277     if (qtwg_ptr->buf[2] != '$')
278         return PARSE_ERROR_NONE;
279 #endif
280
281     int num = tokenize(qtwg_ptr->buf + _(2, 3), 33, zz, 0);
282     if (num < 3)
283         return PARSE_ERROR_TOO_FEW_ARGUMENTS;
284
285     quest_type *q_ptr;
286     q_ptr = &(quest[atoi(zz[0])]);
287     if (parse_qtw_QQ(q_ptr, zz, num))
288         return PARSE_ERROR_NONE;
289
290     if (parse_qtw_QR(q_ptr, zz, num))
291         return PARSE_ERROR_NONE;
292
293     if (zz[1][0] == 'N') {
294         if (init_flags & (INIT_ASSIGN | INIT_SHOW_TEXT | INIT_NAME_ONLY)) {
295             strcpy(q_ptr->name, zz[2]);
296         }
297
298         return PARSE_ERROR_NONE;
299     }
300
301     if (zz[1][0] == 'T') {
302         if (init_flags & INIT_SHOW_TEXT) {
303             strcpy(quest_text[quest_text_line], zz[2]);
304             quest_text_line++;
305         }
306
307         return PARSE_ERROR_NONE;
308     }
309
310     return PARSE_ERROR_GENERIC;
311 }
312
313 static bool parse_qtw_P(player_type *player_ptr, qtwg_type *qtwg_ptr, char **zz)
314 {
315     if (qtwg_ptr->buf[0] != 'P')
316         return FALSE;
317
318     if ((init_flags & INIT_CREATE_DUNGEON) == 0)
319         return TRUE;
320
321     if (tokenize(qtwg_ptr->buf + 2, 2, zz, 0) != 2)
322         return TRUE;
323
324     int panels_y = (*qtwg_ptr->y / SCREEN_HGT);
325     if (*qtwg_ptr->y % SCREEN_HGT)
326         panels_y++;
327
328     floor_type *floor_ptr = player_ptr->current_floor_ptr;
329     floor_ptr->height = panels_y * SCREEN_HGT;
330     int panels_x = (*qtwg_ptr->x / SCREEN_WID);
331     if (*qtwg_ptr->x % SCREEN_WID)
332         panels_x++;
333
334     floor_ptr->width = panels_x * SCREEN_WID;
335     panel_row_min = floor_ptr->height;
336     panel_col_min = floor_ptr->width;
337     if (floor_ptr->inside_quest) {
338         POSITION py = atoi(zz[0]);
339         POSITION px = atoi(zz[1]);
340         player_ptr->y = py;
341         player_ptr->x = px;
342         delete_monster(player_ptr, player_ptr->y, player_ptr->x);
343         return TRUE;
344     }
345
346     if (!player_ptr->oldpx && !player_ptr->oldpy) {
347         player_ptr->oldpy = atoi(zz[0]);
348         player_ptr->oldpx = atoi(zz[1]);
349     }
350
351     return TRUE;
352 }
353
354 static bool parse_qtw_M(qtwg_type *qtwg_ptr, char **zz)
355 {
356     if (qtwg_ptr->buf[0] != 'M')
357         return FALSE;
358
359     if ((tokenize(qtwg_ptr->buf + 2, 2, zz, 0) == 2) == 0)
360         return TRUE;
361
362     if (zz[0][0] == 'T') {
363         max_towns = (TOWN_IDX)atoi(zz[1]);
364     } else if (zz[0][0] == 'Q') {
365         max_q_idx = (QUEST_IDX)atoi(zz[1]);
366     } else if (zz[0][0] == 'R') {
367         max_r_idx = (player_race_type)atoi(zz[1]);
368     } else if (zz[0][0] == 'K') {
369         max_k_idx = (KIND_OBJECT_IDX)atoi(zz[1]);
370     } else if (zz[0][0] == 'V') {
371         max_v_idx = (VAULT_IDX)atoi(zz[1]);
372     } else if (zz[0][0] == 'F') {
373         max_f_idx = (FEAT_IDX)atoi(zz[1]);
374     } else if (zz[0][0] == 'A') {
375         max_a_idx = (ARTIFACT_IDX)atoi(zz[1]);
376     } else if (zz[0][0] == 'E') {
377         max_e_idx = (EGO_IDX)atoi(zz[1]);
378     } else if (zz[0][0] == 'D') {
379         current_world_ptr->max_d_idx = (DUNGEON_IDX)atoi(zz[1]);
380     } else if (zz[0][0] == 'O') {
381         current_world_ptr->max_o_idx = (OBJECT_IDX)atoi(zz[1]);
382     } else if (zz[0][0] == 'M') {
383         current_world_ptr->max_m_idx = (MONSTER_IDX)atoi(zz[1]);
384     } else if (zz[0][0] == 'W') {
385         if (zz[0][1] == 'X')
386             current_world_ptr->max_wild_x = (POSITION)atoi(zz[1]);
387
388         if (zz[0][1] == 'Y')
389             current_world_ptr->max_wild_y = (POSITION)atoi(zz[1]);
390     }
391
392     return TRUE;
393 }
394
395 /*!
396  * @brief 固定マップ (クエスト&街&広域マップ)をフロアに生成する
397  * Parse a sub-file of the "extra info"
398  * @param player_ptr プレーヤーへの参照ポインタ
399  * @param buf 文字列
400  * @param ymin 詳細不明
401  * @param xmin 詳細不明
402  * @param ymax 詳細不明
403  * @param xmax 詳細不明
404  * @param y 詳細不明
405  * @param x 詳細不明
406  * @return エラーコード
407  */
408 parse_error_type generate_fixed_map_floor(player_type *player_ptr, qtwg_type *qtwg_ptr, process_dungeon_file_pf parse_fixed_map)
409 {
410     char *zz[33];
411     if (!qtwg_ptr->buf[0])
412         return PARSE_ERROR_NONE;
413
414     if (iswspace(qtwg_ptr->buf[0]))
415         return PARSE_ERROR_NONE;
416
417     if (qtwg_ptr->buf[0] == '#')
418         return PARSE_ERROR_NONE;
419
420     if (qtwg_ptr->buf[1] != ':')
421         return PARSE_ERROR_GENERIC;
422
423     if (qtwg_ptr->buf[0] == '%')
424         return (*parse_fixed_map)(player_ptr, qtwg_ptr->buf + 2, qtwg_ptr->ymin, qtwg_ptr->xmin, qtwg_ptr->ymax, qtwg_ptr->xmax);
425
426     /* Process "F:<letter>:<terrain>:<cave_info>:<monster>:<object>:<ego>:<artifact>:<trap>:<special>" -- info for dungeon grid */
427     if (qtwg_ptr->buf[0] == 'F')
428         return parse_line_feature(player_ptr->current_floor_ptr, qtwg_ptr->buf);
429
430     if (qtwg_ptr->buf[0] == 'D') {
431         char *s = qtwg_ptr->buf + 2;
432         if (init_flags & INIT_ONLY_BUILDINGS)
433             return PARSE_ERROR_NONE;
434
435         parse_qtw_D(player_ptr, qtwg_ptr, s);
436         (*qtwg_ptr->y)++;
437         return PARSE_ERROR_NONE;
438     }
439
440     parse_error_type parse_result_Q = static_cast<parse_error_type>(parse_qtw_Q(qtwg_ptr, zz));
441     if (parse_result_Q != PARSE_CONTINUE)
442         return parse_result_Q;
443
444     if (qtwg_ptr->buf[0] == 'W')
445         return parse_line_wilderness(player_ptr, qtwg_ptr->buf, qtwg_ptr->xmin, qtwg_ptr->xmax, qtwg_ptr->y, qtwg_ptr->x);
446
447     if (parse_qtw_P(player_ptr, qtwg_ptr, zz))
448         return PARSE_ERROR_NONE;
449
450     if (qtwg_ptr->buf[0] == 'B')
451         return parse_line_building(qtwg_ptr->buf);
452
453     if (parse_qtw_M(qtwg_ptr, zz))
454         return PARSE_ERROR_NONE;
455
456     return PARSE_ERROR_GENERIC;
457 }