OSDN Git Service

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