OSDN Git Service

モンスターの状態変数7種を配列化し, 状態変数の変更を関数化. 各配列の値
[hengband/hengband.git] / src / floors.c
1 /* File: floors.c */
2
3 /* Purpose: management of the saved floor */
4
5 /*
6  * Copyright (c) 2002  Mogami
7  *
8  * This software may be copied and distributed for educational, research, and
9  * not for profit purposes provided that this copyright and statement are
10  * included in all such copies.
11  */
12
13 #include "angband.h"
14 #include "grid.h"
15
16
17 static s16b new_floor_id;       /* floor_id of the destination */
18 static u32b change_floor_mode;  /* Mode flags for changing floor */
19 static u32b latest_visit_mark;  /* Max number of visit_mark */
20
21
22 /*
23  * Initialize saved_floors array.  Make sure that old temporal files
24  * are not remaining as gurbages.
25  */
26 void init_saved_floors(bool force)
27 {
28         char floor_savefile[1024];
29         int i;
30         int fd = -1;
31         int mode = 0644;
32
33 #ifdef SET_UID
34 # ifdef SECURE
35         /* Get "games" permissions */
36         beGames();
37 # endif
38 #endif
39
40         for (i = 0; i < MAX_SAVED_FLOORS; i++)
41         {
42                 saved_floor_type *sf_ptr = &saved_floors[i];
43
44                 /* File name */
45                 sprintf(floor_savefile, "%s.F%02d", savefile, i);
46
47                 /* Grab permissions */
48                 safe_setuid_grab();
49
50                 /* Try to create the file */
51                 fd = fd_make(floor_savefile, mode);
52
53                 /* Drop permissions */
54                 safe_setuid_drop();
55
56                 /* Failed! */
57                 if (fd < 0)
58                 {
59                         if (!force)
60                         {
61 #ifdef JP
62                                 msg_print("¥¨¥é¡¼¡§¸Å¤¤¥Æ¥ó¥Ý¥é¥ê¡¦¥Õ¥¡¥¤¥ë¤¬»Ä¤Ã¤Æ¤¤¤Þ¤¹¡£");
63                                 msg_print("ÊѶòÈÚÅܤòÆó½Å¤Ëµ¯Æ°¤·¤Æ¤¤¤Ê¤¤¤«³Îǧ¤·¤Æ¤¯¤À¤µ¤¤¡£");
64                                 msg_print("²áµî¤ËÊѶòÈÚÅܤ¬¥¯¥é¥Ã¥·¥å¤·¤¿¾ì¹ç¤Ï°ì»þ¥Õ¥¡¥¤¥ë¤ò");
65                                 msg_print("¶¯À©Åª¤Ëºï½ü¤·¤Æ¼Â¹Ô¤ò³¤±¤é¤ì¤Þ¤¹¡£");
66                                 if (!get_check("¶¯À©Åª¤Ëºï½ü¤·¤Æ¤â¤è¤í¤·¤¤¤Ç¤¹¤«¡©")) quit("¼Â¹ÔÃæ»ß");
67 #else
68                                 msg_print("Error: There are old temporal files.");
69                                 msg_print("Make sure you are not running two game processes simultaneously.");
70                                 msg_print("If the temporal files are garbages of old crashed process, ");
71                                 msg_print("you can delete it safely.");
72                                 if (!get_check("Do you delete old temporal files? ")) quit("Aborted.");
73 #endif
74                                 force = TRUE;
75                         }
76                 }
77                 else
78                 {
79                         /* Close the "fd" */
80                         (void)fd_close(fd);
81                 }
82
83                 /* Grab permissions */
84                 safe_setuid_grab();
85
86                 /* Simply kill the temporal file */ 
87                 (void)fd_kill(floor_savefile);
88
89                 /* Drop permissions */
90                 safe_setuid_drop();
91
92                 sf_ptr->floor_id = 0;
93         }
94
95         /* No floor_id used yet (No.0 is reserved to indicate non existance) */
96         max_floor_id = 1;
97
98         /* vist_mark is from 1 */
99         latest_visit_mark = 1;
100
101         /* A sign to mark temporal files */
102         saved_floor_file_sign = time(NULL);
103
104         /* No next floor yet */
105         new_floor_id = 0;
106
107         /* No change floor mode yet */
108         change_floor_mode = 0;
109
110 #ifdef SET_UID
111 # ifdef SECURE
112         /* Drop "games" permissions */
113         bePlayer();
114 # endif
115 #endif
116 }
117
118
119 /*
120  * Kill temporal files
121  * Should be called just before the game quit.
122  */
123 void clear_saved_floor_files(void)
124 {
125         char floor_savefile[1024];
126         int i;
127
128 #ifdef SET_UID
129 # ifdef SECURE
130         /* Get "games" permissions */
131         beGames();
132 # endif
133 #endif
134
135         for (i = 0; i < MAX_SAVED_FLOORS; i++)
136         {
137                 saved_floor_type *sf_ptr = &saved_floors[i];
138
139                 /* No temporal file */
140                 if (!sf_ptr->floor_id) continue;
141                 if (sf_ptr->floor_id == p_ptr->floor_id) continue;
142
143                 /* File name */
144                 sprintf(floor_savefile, "%s.F%02d", savefile, i);
145
146                 /* Grab permissions */
147                 safe_setuid_grab();
148
149                 /* Simply kill the temporal file */ 
150                 (void)fd_kill(floor_savefile);
151
152                 /* Drop permissions */
153                 safe_setuid_drop();
154         }
155
156 #ifdef SET_UID
157 # ifdef SECURE
158         /* Drop "games" permissions */
159         bePlayer();
160 # endif
161 #endif
162 }
163
164
165 /*
166  * Get a pointer for an item of the saved_floors array.
167  */
168 saved_floor_type *get_sf_ptr(s16b floor_id)
169 {
170         int i;
171
172         /* floor_id No.0 indicates no floor */
173         if (!floor_id) return NULL;
174
175         for (i = 0; i < MAX_SAVED_FLOORS; i++)
176         {
177                 saved_floor_type *sf_ptr = &saved_floors[i];
178
179                 if (sf_ptr->floor_id == floor_id) return sf_ptr;
180         }
181
182         /* None found */
183         return NULL;
184 }
185
186
187 /*
188  * kill a saved floor and get an empty space
189  */
190 static void kill_saved_floor(saved_floor_type *sf_ptr)
191 {
192         char floor_savefile[1024];
193
194         /* Paranoia */
195         if (!sf_ptr) return;
196
197         /* Already empty */
198         if (!sf_ptr->floor_id) return;
199
200         if (sf_ptr->floor_id == p_ptr->floor_id)
201         {
202                 /* Kill current floor */
203                 p_ptr->floor_id = 0;
204
205                 /* Current floor doesn't have temporal file */
206         }
207         else 
208         {
209                 /* File name */
210                 sprintf(floor_savefile, "%s.F%02d", savefile, (int)sf_ptr->savefile_id);
211
212                 /* Grab permissions */
213                 safe_setuid_grab();
214
215                 /* Simply kill the temporal file */ 
216                 (void)fd_kill(floor_savefile);
217
218                 /* Drop permissions */
219                 safe_setuid_drop();
220         }
221
222         /* No longer exists */
223         sf_ptr->floor_id = 0;
224 }
225
226
227 /*
228  * Initialize new saved floor and get its floor id.  If number of
229  * saved floors are already MAX_SAVED_FLOORS, kill the oldest one.
230  */
231 s16b get_new_floor_id(void)
232 {
233         saved_floor_type *sf_ptr;
234         int i;
235
236         /* Look for empty space */
237         for (i = 0; i < MAX_SAVED_FLOORS; i++)
238         {
239                 sf_ptr = &saved_floors[i];
240
241                 if (!sf_ptr->floor_id) break;
242         }
243
244         /* None found */
245         if (i == MAX_SAVED_FLOORS)
246         {
247                 int oldest = 0;
248                 u32b oldest_visit = 0xffffffffL;
249
250                 /* Search for oldest */
251                 for (i = 0; i < MAX_SAVED_FLOORS; i++)
252                 {
253                         sf_ptr = &saved_floors[i];
254
255                         /* Don't kill current floor */
256                         if (sf_ptr->floor_id == p_ptr->floor_id) continue;
257
258                         /* Don't kill newer */
259                         if (sf_ptr->visit_mark > oldest_visit) continue;
260
261                         oldest = i;
262                         oldest_visit = sf_ptr->visit_mark;
263                 }
264
265                 /* Kill oldest saved floor */
266                 sf_ptr = &saved_floors[oldest];
267                 kill_saved_floor(sf_ptr);
268
269                 /* Use it */
270                 i = oldest;
271         }
272
273         /* Prepare new floor data */
274         sf_ptr->savefile_id = i;
275         sf_ptr->floor_id = max_floor_id;
276         sf_ptr->last_visit = 0;
277         sf_ptr->upper_floor_id = 0;
278         sf_ptr->lower_floor_id = 0;
279         sf_ptr->visit_mark = latest_visit_mark++;
280
281         /* sf_ptr->dun_level may be changed later */
282         sf_ptr->dun_level = dun_level;
283
284
285         /* Increment number of floor_id */
286         if (max_floor_id < MAX_SHORT) max_floor_id++;
287
288         /* 32767 floor_ids are all used up!  Re-use ancient IDs */
289         else max_floor_id = 1;
290
291         return sf_ptr->floor_id;
292 }
293
294
295 /*
296  * Prepare mode flags of changing floor
297  */
298 void prepare_change_floor_mode(u32b mode)
299 {
300         change_floor_mode |= mode;
301 }
302
303
304 /*
305  * Builds the dead end
306  */
307 static void build_dead_end(void)
308 {
309         int x,y;
310
311         /* Clear and empty the cave */
312         clear_cave();
313
314         /* Fill the arrays of floors and walls in the good proportions */
315         set_floor_and_wall(0);
316
317         /* Smallest area */
318         cur_hgt = SCREEN_HGT;
319         cur_wid = SCREEN_WID;
320
321         /* Filled with permanent walls */
322         for (y = 0; y < MAX_HGT; y++)
323         {
324                 for (x = 0; x < MAX_WID; x++)
325                 {
326                         /* Create "solid" perma-wall */
327                         place_solid_perm_bold(y, x);
328                 }
329         }
330
331         /* Place at center of the floor */
332         py = cur_hgt / 2;
333         px = cur_wid / 2;
334
335         /* Give one square */
336         place_floor_bold(py, px);
337 }
338
339
340 /* Maximum number of preservable pets */
341 #define MAX_PARTY_MON 21
342
343 static monster_type party_mon[MAX_PARTY_MON];
344
345
346 /*
347  * Preserve_pets
348  */
349 static void preserve_pet(void)
350 {
351         int num, i;
352
353         for (num = 0; num < MAX_PARTY_MON; num++)
354         {
355                 party_mon[num].r_idx = 0;
356         }
357
358         if (p_ptr->riding)
359         {
360                 monster_type *m_ptr = &m_list[p_ptr->riding];
361
362                 /* Pet of other pet don't follow. */
363                 if (m_ptr->parent_m_idx)
364                 {
365                         p_ptr->riding = 0;
366                         p_ptr->pet_extra_flags &= ~(PF_RYOUTE);
367                         p_ptr->riding_ryoute = p_ptr->old_riding_ryoute = FALSE;
368                 }
369                 else
370                 {
371                         /* Preserve the mount */
372                         COPY(&party_mon[0], m_ptr, monster_type);
373
374                         /* Delete from this floor */
375                         delete_monster_idx(p_ptr->riding);
376                 }
377         }
378
379         /*
380          * If player is in wild mode, no pets are preserved
381          * except a monster whom player riding
382          */
383         if (!p_ptr->wild_mode && !p_ptr->inside_arena && !p_ptr->inside_battle)
384         {
385                 for (i = m_max - 1, num = 1; (i >= 1 && num < MAX_PARTY_MON); i--)
386                 {
387                         monster_type *m_ptr = &m_list[i];
388
389                         if (!m_ptr->r_idx) continue;
390                         if (!is_pet(m_ptr)) continue;
391                         if (i == p_ptr->riding) continue;
392
393                         if (reinit_wilderness)
394                         {
395                                 /* Don't lose sight of pets when getting a Quest */
396                         }
397                         else
398                         {
399                                 int dis = distance(py, px, m_ptr->fy, m_ptr->fx);
400
401                                 /* Confused (etc.) monsters don't follow. */
402                                 if (MON_CONFUSED(m_ptr) || MON_STUNNED(m_ptr) || MON_CSLEEP(m_ptr)) continue;
403
404                                 /* Pet of other pet don't follow. */
405                                 if (m_ptr->parent_m_idx) continue;
406
407                                 /*
408                                  * Pets with nickname will follow even from 3 blocks away
409                                  * when you or the pet can see the other.
410                                  */
411                                 if (m_ptr->nickname && 
412                                     ((player_has_los_bold(m_ptr->fy, m_ptr->fx) && projectable(py, px, m_ptr->fy, m_ptr->fx)) ||
413                                      (los(m_ptr->fy, m_ptr->fx, py, px) && projectable(m_ptr->fy, m_ptr->fx, py, px))))
414                                 {
415                                         if (dis > 3) continue;
416                                 }
417                                 else
418                                 {
419                                         if (dis > 1) continue;
420                                 }
421                         }
422
423                         COPY(&party_mon[num], &m_list[i], monster_type);
424
425                         num++;
426
427                         /* Delete from this floor */
428                         delete_monster_idx(i);
429                 }
430         }
431
432         if (record_named_pet)
433         {
434                 for (i = m_max - 1; i >=1; i--)
435                 {
436                         monster_type *m_ptr = &m_list[i];
437                         char m_name[80];
438
439                         if (!m_ptr->r_idx) continue;
440                         if (!is_pet(m_ptr)) continue;
441                         if (!m_ptr->nickname) continue;
442                         if (p_ptr->riding == i) continue;
443
444                         monster_desc(m_name, m_ptr, MD_ASSUME_VISIBLE | MD_INDEF_VISIBLE);
445                         do_cmd_write_nikki(NIKKI_NAMED_PET, 4, m_name);
446                 }
447         }
448
449
450         /* Pet of other pet may disappear. */
451         for (i = m_max - 1; i >=1; i--)
452         {
453                 monster_type *m_ptr = &m_list[i];
454
455                 /* Are there its parent? */
456                 if (m_ptr->parent_m_idx && !m_list[m_ptr->parent_m_idx].r_idx)
457                 {
458                         /* Its parent have gone, it also goes away. */
459
460                         if (is_seen(m_ptr))
461                         {
462                                 char m_name[80];
463
464                                 /* Acquire the monster name */
465                                 monster_desc(m_name, m_ptr, 0);
466
467 #ifdef JP
468                                 msg_format("%s¤Ï¾Ã¤¨µî¤Ã¤¿¡ª", m_name);
469 #else
470                                 msg_format("%^s disappears!", m_name);
471 #endif
472                         }
473
474                         /* Delete the monster */
475                         delete_monster_idx(i);
476                 }
477         }
478 }
479
480
481 /*
482  * Pre-calculate the racial counters of preserved pets
483  * To prevent multiple generation of unique monster who is the minion of player
484  */
485 void precalc_cur_num_of_pet(void)
486 {
487         monster_type *m_ptr;
488         int i;
489         int max_num = p_ptr->wild_mode ? 1 : MAX_PARTY_MON;
490
491         for (i = 0; i < max_num; i++)
492         {
493                 m_ptr = &party_mon[i];
494
495                 /* Skip empty monsters */
496                 if (!m_ptr->r_idx) continue;
497
498                 /* Hack -- Increase the racial counter */
499                 real_r_ptr(m_ptr)->cur_num++;
500         }
501 }
502
503
504 /*
505  * Place preserved pet monsters on new floor
506  */
507 static void place_pet(void)
508 {
509         int i;
510         int max_num = p_ptr->wild_mode ? 1 : MAX_PARTY_MON;
511
512         for (i = 0; i < max_num; i++)
513         {
514                 int cy, cx, m_idx;
515
516                 if (!(party_mon[i].r_idx)) continue;
517
518                 if (i == 0)
519                 {
520                         m_idx = m_pop();
521                         p_ptr->riding = m_idx;
522                         if (m_idx)
523                         {
524                                 cy = py;
525                                 cx = px;
526                         }
527                 }
528                 else
529                 {
530                         int j, d;
531
532                         for (d = 1; d < 6; d++)
533                         {
534                                 for (j = 1000; j > 0; j--)
535                                 {
536                                         scatter(&cy, &cx, py, px, d, 0);
537                                         if (monster_can_enter(cy, cx, &r_info[party_mon[i].r_idx], 0)) break;
538                                 }
539                                 if (j) break;
540                         }
541                         m_idx = (d == 6) ? 0 : m_pop();
542                 }
543
544                 if (m_idx)
545                 {
546                         monster_type *m_ptr = &m_list[m_idx];
547                         monster_race *r_ptr;
548
549                         cave[cy][cx].m_idx = m_idx;
550
551                         m_ptr->r_idx = party_mon[i].r_idx;
552
553                         /* Copy all member of the structure */
554                         *m_ptr = party_mon[i];
555                         r_ptr = real_r_ptr(m_ptr);
556
557                         m_ptr->fy = cy;
558                         m_ptr->fx = cx;
559                         m_ptr->ml = TRUE;
560                         m_ptr->mtimed[MTIMED_CSLEEP] = 0;
561
562                         /* Paranoia */
563                         m_ptr->hold_o_idx = 0;
564                         m_ptr->target_y = 0;
565
566                         if ((r_ptr->flags1 & RF1_FORCE_SLEEP) && !ironman_nightmare)
567                         {
568                                 /* Monster is still being nice */
569                                 m_ptr->mflag |= (MFLAG_NICE);
570
571                                 /* Must repair monsters */
572                                 repair_monsters = TRUE;
573                         }
574
575                         /* Update the monster */
576                         update_mon(m_idx, TRUE);
577                         lite_spot(cy, cx);
578
579                         /* Pre-calculated in precalc_cur_num_of_pet() */
580                         /* r_ptr->cur_num++; */
581
582                         /* Hack -- Count the number of "reproducers" */
583                         if (r_ptr->flags2 & RF2_MULTIPLY) num_repro++;
584
585                         /* Hack -- Notice new multi-hued monsters */
586                         {
587                                 monster_race *ap_r_ptr = &r_info[m_ptr->ap_r_idx];
588                                 if (ap_r_ptr->flags1 & (RF1_ATTR_MULTI | RF1_SHAPECHANGER))
589                                         shimmer_monsters = TRUE;
590                         }
591                 }
592                 else
593                 {
594                         monster_type *m_ptr = &party_mon[i];
595                         monster_race *r_ptr = real_r_ptr(m_ptr);
596                         char m_name[80];
597
598                         monster_desc(m_name, m_ptr, 0);
599 #ifdef JP
600                         msg_format("%s¤È¤Ï¤°¤ì¤Æ¤·¤Þ¤Ã¤¿¡£", m_name);
601 #else
602                         msg_format("You have lost sight of %s.", m_name);
603 #endif
604                         if (record_named_pet && m_ptr->nickname)
605                         {
606                                 monster_desc(m_name, m_ptr, MD_INDEF_VISIBLE);
607                                 do_cmd_write_nikki(NIKKI_NAMED_PET, 5, m_name);
608                         }
609
610                         /* Pre-calculated in precalc_cur_num_of_pet(), but need to decrease */
611                         if (r_ptr->cur_num) r_ptr->cur_num--;
612                 }
613         }
614
615         /* For accuracy of precalc_cur_num_of_pet() */
616         C_WIPE(party_mon, MAX_PARTY_MON, monster_type);
617 }
618
619
620 /*
621  * Hack -- Update location of unique monsters and artifacts
622  *
623  * The r_ptr->floor_id and a_ptr->floor_id are not updated correctly
624  * while new floor creation since dungeons may be re-created by
625  * auto-scum option.
626  */
627 static void update_unique_artifact(s16b cur_floor_id)
628 {
629         int i;
630
631         /* Maintain unique monsters */
632         for (i = 1; i < m_max; i++)
633         {
634                 monster_race *r_ptr;
635                 monster_type *m_ptr = &m_list[i];
636
637                 /* Skip dead monsters */
638                 if (!m_ptr->r_idx) continue;
639
640                 /* Extract real monster race */
641                 r_ptr = real_r_ptr(m_ptr);
642
643                 /* Memorize location of the unique monster */
644                 if ((r_ptr->flags1 & RF1_UNIQUE) ||
645                     (r_ptr->flags7 & RF7_NAZGUL))
646                 {
647                         r_ptr->floor_id = cur_floor_id;
648                 }
649         }
650
651         /* Maintain artifatcs */
652         for (i = 1; i < o_max; i++)
653         {
654                 object_type *o_ptr = &o_list[i];
655
656                 /* Skip dead objects */
657                 if (!o_ptr->k_idx) continue;
658
659                 /* Memorize location of the artifact */
660                 if (object_is_fixed_artifact(o_ptr))
661                 {
662                         a_info[o_ptr->name1].floor_id = cur_floor_id;
663                 }
664         }
665 }
666
667
668 /*
669  * When a monster is at a place where player will return,
670  * Get out of the my way!
671  */
672 static void get_out_monster(void)
673 {
674         int tries = 0;
675         int dis = 1;
676         int oy = py;
677         int ox = px;
678         int m_idx = cave[oy][ox].m_idx;
679
680         /* Nothing to do if no monster */
681         if (!m_idx) return;
682
683         /* Look until done */
684         while (TRUE)
685         {
686                 monster_type *m_ptr;
687
688                 /* Pick a (possibly illegal) location */
689                 int ny = rand_spread(oy, dis);
690                 int nx = rand_spread(ox, dis);
691
692                 tries++;
693
694                 /* Stop after 1000 tries */
695                 if (tries > 10000) return;
696
697                 /*
698                  * Increase distance after doing enough tries
699                  * compared to area of possible space
700                  */
701                 if (tries > 20 * dis * dis) dis++;
702
703                 /* Ignore illegal locations */
704                 if (!in_bounds(ny, nx)) continue;
705
706                 /* Require "empty" floor space */
707                 if (!cave_empty_bold(ny, nx)) continue;
708
709                 /* Hack -- no teleport onto glyph of warding */
710                 if (is_glyph_grid(&cave[ny][nx])) continue;
711                 if (is_explosive_rune_grid(&cave[ny][nx])) continue;
712
713                 /* ...nor onto the Pattern */
714                 if (pattern_tile(ny, nx)) continue;
715
716                 /*** It's a good place ***/
717
718                 m_ptr = &m_list[m_idx];
719
720                 /* Update the old location */
721                 cave[oy][ox].m_idx = 0;
722
723                 /* Update the new location */
724                 cave[ny][nx].m_idx = m_idx;
725
726                 /* Move the monster */
727                 m_ptr->fy = ny;
728                 m_ptr->fx = nx; 
729
730                 /* No need to do update_mon() */
731
732                 /* Success */
733                 return;
734         }
735 }
736
737
738 /*
739  * Is this feature has special meaning (except floor_id) with c_ptr->special?
740  */
741 #define feat_uses_special(F) (have_flag(f_info[(F)].flags, FF_SPECIAL))
742
743
744 /*
745  * Virtually teleport onto the stairs that is connecting between two
746  * floors.
747  *
748  * Teleport level spell and trap doors will always lead the player to
749  * the one of the floors connected by the one of the stairs in the
750  * current floor.
751  */
752 static void locate_connected_stairs(saved_floor_type *sf_ptr)
753 {
754         int x, y, sx = 0, sy = 0;
755         int x_table[20];
756         int y_table[20];
757         int num = 0;
758         int i;
759
760         /* Search usable stairs */
761         for (y = 0; y < cur_hgt; y++)
762         {
763                 for (x = 0; x < cur_wid; x++)
764                 {
765                         cave_type *c_ptr = &cave[y][x];
766                         feature_type *f_ptr = &f_info[c_ptr->feat];
767                         bool ok = FALSE;
768
769                         if (change_floor_mode & CFM_UP)
770                         {
771                                 if (have_flag(f_ptr->flags, FF_LESS) && have_flag(f_ptr->flags, FF_STAIRS) &&
772                                     !have_flag(f_ptr->flags, FF_SPECIAL))
773                                 {
774                                         ok = TRUE;
775
776                                         /* Found fixed stairs? */
777                                         if (c_ptr->special &&
778                                             c_ptr->special == sf_ptr->upper_floor_id)
779                                         {
780                                                 sx = x;
781                                                 sy = y;
782                                         }
783                                 }
784                         }
785
786                         else if (change_floor_mode & CFM_DOWN)
787                         {
788                                 if (have_flag(f_ptr->flags, FF_MORE) && have_flag(f_ptr->flags, FF_STAIRS) &&
789                                     !have_flag(f_ptr->flags, FF_SPECIAL))
790                                 {
791                                         ok = TRUE;
792
793                                         /* Found fixed stairs */
794                                         if (c_ptr->special &&
795                                             c_ptr->special == sf_ptr->lower_floor_id)
796                                         {
797                                                 sx = x;
798                                                 sy = y;
799                                         }
800                                 }
801                         }
802
803                         else
804                         {
805                                 if (have_flag(f_ptr->flags, FF_BLDG))
806                                 {
807                                         ok = TRUE;
808                                 }
809                         }
810
811                         if (ok && (num < 20))
812                         {
813                                 x_table[num] = x;
814                                 y_table[num] = y;
815                                 num++;
816                         }
817                 }
818         }
819
820         if (sx)
821         {
822                 /* Already fixed */
823                 py = sy;
824                 px = sx;
825         }
826         else if (!num)
827         {
828                 /* No stairs found! -- No return */
829                 prepare_change_floor_mode(CFM_RAND_PLACE | CFM_NO_RETURN);
830
831                 /* Mega Hack -- It's not the stairs you enter.  Disable it.  */
832                 if (!feat_uses_special(cave[py][px].feat)) cave[py][px].special = 0;
833         }
834         else
835         {
836                 /* Choose random one */
837                 i = randint0(num);
838
839                 /* Point stair location */
840                 py = y_table[i];
841                 px = x_table[i];
842         }
843 }
844
845 /*
846  * Maintain quest monsters, mark next floor_id at stairs, save current
847  * floor, and prepare to enter next floor.
848  */
849 void leave_floor(void)
850 {
851         cave_type *c_ptr = NULL;
852         feature_type *f_ptr;
853         saved_floor_type *sf_ptr;
854         int quest_r_idx = 0;
855         int i;
856
857         /* Preserve pets and prepare to take these to next floor */
858         preserve_pet();
859
860         /* Remove all mirrors without explosion */
861         remove_all_mirrors(FALSE);
862
863         if (p_ptr->special_defense & NINJA_S_STEALTH) set_superstealth(FALSE);
864
865         /* New floor is not yet prepared */
866         new_floor_id = 0;
867
868         /* Temporary get a floor_id (for Arena) */
869         if (!p_ptr->floor_id &&
870             (change_floor_mode & CFM_SAVE_FLOORS) &&
871             !(change_floor_mode & CFM_NO_RETURN))
872         {
873             /* Get temporal floor_id */
874             p_ptr->floor_id = get_new_floor_id();
875         }
876
877
878         /* Search the quest monster index */
879         for (i = 0; i < max_quests; i++)
880         {
881                 if ((quest[i].status == QUEST_STATUS_TAKEN) &&
882                     ((quest[i].type == QUEST_TYPE_KILL_LEVEL) ||
883                     (quest[i].type == QUEST_TYPE_RANDOM)) &&
884                     (quest[i].level == dun_level) &&
885                     (dungeon_type == quest[i].dungeon) &&
886                     !(quest[i].flags & QUEST_FLAG_PRESET))
887                 {
888                         quest_r_idx = quest[i].r_idx;
889                 }
890         }
891
892         /* Maintain quest monsters */
893         for (i = 1; i < m_max; i++)
894         {
895                 monster_race *r_ptr;
896                 monster_type *m_ptr = &m_list[i];
897
898                 /* Skip dead monsters */
899                 if (!m_ptr->r_idx) continue;
900
901                 /* Only maintain quest monsters */
902                 if (quest_r_idx != m_ptr->r_idx) continue;
903
904                 /* Extract real monster race */
905                 r_ptr = real_r_ptr(m_ptr);
906
907                 /* Ignore unique monsters */
908                 if ((r_ptr->flags1 & RF1_UNIQUE) ||
909                     (r_ptr->flags7 & RF7_NAZGUL)) continue;
910
911                 /* Delete non-unique quest monsters */
912                 delete_monster_idx(i);
913         }
914
915         /* Check if there is a same item */
916         for (i = 0; i < INVEN_PACK; i++)
917         {
918                 object_type *o_ptr = &inventory[i];
919
920                 /* Skip dead objects */
921                 if (!o_ptr->k_idx) continue;
922
923                 /* Delete old memorized location of the artifact */
924                 if (object_is_fixed_artifact(o_ptr))
925                 {
926                         a_info[o_ptr->name1].floor_id = 0;
927                 }
928         }
929
930         /* Extract current floor info or NULL */
931         sf_ptr = get_sf_ptr(p_ptr->floor_id);
932
933         /* Choose random stairs */
934         if ((change_floor_mode & CFM_RAND_CONNECT) && p_ptr->floor_id)
935         {
936                 locate_connected_stairs(sf_ptr);
937         }
938
939         /* Extract new dungeon level */
940         if (change_floor_mode & CFM_SAVE_FLOORS)
941         {
942                 /* Extract stair position */
943                 c_ptr = &cave[py][px];
944                 f_ptr = &f_info[c_ptr->feat];
945
946                 /* Get back to old saved floor? */
947                 if (c_ptr->special && !have_flag(f_ptr->flags, FF_SPECIAL) && get_sf_ptr(c_ptr->special))
948                 {
949                         /* Saved floor is exist.  Use it. */
950                         new_floor_id = c_ptr->special;
951                 }
952
953                 /* Mark shaft up/down */
954                 if (have_flag(f_ptr->flags, FF_STAIRS) && have_flag(f_ptr->flags, FF_SHAFT))
955                 {
956                         prepare_change_floor_mode(CFM_SHAFT);
957                 }
958         }
959
960         /* Climb up/down some sort of stairs */
961         if (change_floor_mode & (CFM_DOWN | CFM_UP))
962         {
963                 int move_num = 0;
964
965                 /* Extract level movement number */
966                 if (change_floor_mode & CFM_DOWN) move_num = 1;
967                 else if (change_floor_mode & CFM_UP) move_num = -1;
968
969                 /* Shafts are deeper than normal stairs */
970                 if (change_floor_mode & CFM_SHAFT)
971                         move_num += SGN(move_num);
972
973                 /* Get out from or Enter the dungeon */
974                 if (change_floor_mode & CFM_DOWN)
975                 {
976                         if (!dun_level)
977                                 move_num = d_info[dungeon_type].mindepth;
978                 }
979                 else if (change_floor_mode & CFM_UP)
980                 {
981                         if (dun_level + move_num < d_info[dungeon_type].mindepth)
982                                 move_num = -dun_level;
983                 }
984
985                 dun_level += move_num;
986         }
987
988         /* Leaving the dungeon to town */
989         if (!dun_level && dungeon_type)
990         {
991                 p_ptr->leaving_dungeon = TRUE;
992                 if (!vanilla_town && !lite_town)
993                 {
994                         p_ptr->wilderness_y = d_info[dungeon_type].dy;
995                         p_ptr->wilderness_x = d_info[dungeon_type].dx;
996                 }
997                 p_ptr->recall_dungeon = dungeon_type;
998                 dungeon_type = 0;
999
1000                 /* Reach to the surface -- Clear all saved floors */
1001                 change_floor_mode &= ~CFM_SAVE_FLOORS;
1002         }
1003
1004         /* Kill some old saved floors */
1005         if (!(change_floor_mode & CFM_SAVE_FLOORS))
1006         {
1007                 int i;
1008
1009                 /* Kill all saved floors */
1010                 for (i = 0; i < MAX_SAVED_FLOORS; i++)
1011                         kill_saved_floor(&saved_floors[i]);
1012
1013                 /* Reset visit_mark count */
1014                 latest_visit_mark = 1;
1015         }
1016         else if (change_floor_mode & CFM_NO_RETURN)
1017         {
1018                 /* Kill current floor */
1019                 kill_saved_floor(sf_ptr);
1020         }
1021
1022         /* No current floor -- Left/Enter dungeon etc... */
1023         if (!p_ptr->floor_id)
1024         {
1025                 /* No longer need to save current floor */
1026                 return;
1027         }
1028
1029
1030         /* Mark next floor_id on the previous floor */
1031         if (!new_floor_id)
1032         {
1033                 /* Get new id */
1034                 new_floor_id = get_new_floor_id();
1035
1036                 /* Connect from here */
1037                 if (c_ptr && !feat_uses_special(c_ptr->feat))
1038                 {
1039                         c_ptr->special = new_floor_id;
1040                 }
1041         }
1042
1043         /* Fix connection -- level teleportation or trap door */
1044         if (change_floor_mode & CFM_RAND_CONNECT)
1045         {
1046                 if (change_floor_mode & CFM_UP)
1047                         sf_ptr->upper_floor_id = new_floor_id;
1048                 else if (change_floor_mode & CFM_DOWN)
1049                         sf_ptr->lower_floor_id = new_floor_id;
1050         }
1051
1052         /* If you can return, you need to save previous floor */
1053         if ((change_floor_mode & CFM_SAVE_FLOORS) &&
1054             !(change_floor_mode & CFM_NO_RETURN))
1055         {
1056                 /* Get out of the my way! */
1057                 get_out_monster();
1058
1059                 /* Record the last visit turn of current floor */
1060                 sf_ptr->last_visit = turn;
1061
1062                 /* Forget the lite */
1063                 forget_lite();
1064
1065                 /* Forget the view */
1066                 forget_view();
1067
1068                 /* Forget the view */
1069                 clear_mon_lite();
1070
1071                 /* Save current floor */
1072                 if (!save_floor(sf_ptr, 0))
1073                 {
1074                         /* Save failed -- No return */
1075                         prepare_change_floor_mode(CFM_NO_RETURN);
1076
1077                         /* Kill current floor */
1078                         kill_saved_floor(get_sf_ptr(p_ptr->floor_id));
1079                 }
1080         }
1081 }
1082
1083
1084 /*
1085  * Enter new floor.  If the floor is an old saved floor, it will be
1086  * restored from the temporal file.  If the floor is new one, new cave
1087  * will be generated.
1088  */
1089 void change_floor(void)
1090 {
1091         saved_floor_type *sf_ptr;
1092         bool loaded = FALSE;
1093
1094         /* The dungeon is not ready */
1095         character_dungeon = FALSE;
1096
1097         /* No longer in the trap detecteded region */
1098         p_ptr->dtrap = FALSE;
1099
1100         /* Mega-Hack -- no panel yet */
1101         panel_row_min = 0;
1102         panel_row_max = 0;
1103         panel_col_min = 0;
1104         panel_col_max = 0;
1105
1106         /* Mega-Hack -- not ambushed on the wildness? */
1107         ambush_flag = FALSE;
1108
1109         /* No saved floors (On the surface etc.) */
1110         if (!(change_floor_mode & CFM_SAVE_FLOORS) &&
1111             !(change_floor_mode & CFM_FIRST_FLOOR))
1112         {
1113                 /* Create cave */
1114                 generate_cave();
1115
1116                 /* Paranoia -- No new saved floor */
1117                 new_floor_id = 0;
1118         }
1119
1120         /* In the dungeon */
1121         else
1122         {
1123                 /* No floor_id yet */
1124                 if (!new_floor_id)
1125                 {
1126                         /* Get new id */
1127                         new_floor_id = get_new_floor_id();
1128                 }
1129
1130                 /* Pointer for infomations of new floor */
1131                 sf_ptr = get_sf_ptr(new_floor_id);
1132
1133                 /* Try to restore old floor */
1134                 if (sf_ptr->last_visit)
1135                 {
1136                         /* Old saved floor is exist */
1137                         if (load_floor(sf_ptr, 0))
1138                         {
1139                                 loaded = TRUE;
1140
1141                                 /* Forbid return stairs */
1142                                 if (change_floor_mode & CFM_NO_RETURN)
1143                                 {
1144                                         cave_type *c_ptr = &cave[py][px];
1145
1146                                         if (!feat_uses_special(c_ptr->feat))
1147                                         {
1148                                                 if (change_floor_mode & (CFM_DOWN | CFM_UP))
1149                                                 {
1150                                                         /* Reset to floor */
1151                                                         c_ptr->feat = floor_type[randint0(100)];
1152                                                 }
1153
1154                                                 c_ptr->special = 0;
1155                                         }
1156                                 }
1157                         }
1158                 }
1159
1160                 /*
1161                  * Set lower/upper_floor_id of new floor when the new
1162                  * floor is right-above/right-under the current floor.
1163                  *
1164                  * Stair creation/Teleport level/Trap door will take
1165                  * you the same floor when you used it later again.
1166                  */
1167                 if (p_ptr->floor_id)
1168                 {
1169                         saved_floor_type *cur_sf_ptr = get_sf_ptr(p_ptr->floor_id);
1170
1171                         if (change_floor_mode & CFM_UP)
1172                         {
1173                                 /* New floor is right-above */
1174                                 if (cur_sf_ptr->upper_floor_id == new_floor_id)
1175                                         sf_ptr->lower_floor_id = p_ptr->floor_id;
1176                         }
1177                         else if (change_floor_mode & CFM_DOWN)
1178                         {
1179                                 /* New floor is right-under */
1180                                 if (cur_sf_ptr->lower_floor_id == new_floor_id)
1181                                         sf_ptr->upper_floor_id = p_ptr->floor_id;
1182                         }
1183                 }
1184
1185                 /* Maintain monsters and artifacts */
1186                 if (loaded)
1187                 {
1188                         int i;
1189                         s32b absence_ticks = (turn - sf_ptr->last_visit) / TURNS_PER_TICK;
1190                         int alloc_chance = d_info[dungeon_type].max_m_alloc_chance;
1191                         int alloc_times;
1192
1193                         /* Maintain monsters */
1194                         for (i = 1; i < m_max; i++)
1195                         {
1196                                 monster_race *r_ptr;
1197                                 monster_type *m_ptr = &m_list[i];
1198
1199                                 /* Skip dead monsters */
1200                                 if (!m_ptr->r_idx) continue;
1201
1202                                 if (!is_pet(m_ptr))
1203                                 {
1204                                         /* Restore HP */
1205                                         m_ptr->hp = m_ptr->maxhp = m_ptr->max_maxhp;
1206
1207                                         /* Remove timed status (except MTIMED_CSLEEP) */
1208                                         (void)set_monster_fast(i, 0);
1209                                         (void)set_monster_slow(i, 0);
1210                                         (void)set_monster_stunned(i, 0);
1211                                         (void)set_monster_confused(i, 0);
1212                                         (void)set_monster_monfear(i, 0);
1213                                         (void)set_monster_invulner(i, 0, FALSE);
1214                                 }
1215
1216                                 /* Extract real monster race */
1217                                 r_ptr = real_r_ptr(m_ptr);
1218
1219                                 /* Ignore non-unique */
1220                                 if (!(r_ptr->flags1 & RF1_UNIQUE) &&
1221                                     !(r_ptr->flags7 & RF7_NAZGUL)) continue;
1222
1223                                 /* Appear at a different floor? */
1224                                 if (r_ptr->floor_id != new_floor_id)
1225                                 {
1226                                         /* Disapper from here */
1227                                         delete_monster_idx(i);
1228                                 }
1229                         }
1230
1231                         /* Maintain artifatcs */
1232                         for (i = 1; i < o_max; i++)
1233                         {
1234                                 object_type *o_ptr = &o_list[i];
1235
1236                                 /* Skip dead objects */
1237                                 if (!o_ptr->k_idx) continue;
1238
1239                                 /* Ignore non-artifact */
1240                                 if (!object_is_fixed_artifact(o_ptr)) continue;
1241
1242                                 /* Appear at a different floor? */
1243                                 if (a_info[o_ptr->name1].floor_id != new_floor_id)
1244                                 {
1245                                         /* Disappear from here */
1246                                         delete_object_idx(i);
1247                                 }
1248                                 else
1249                                 {
1250                                         /* Cancel preserve */
1251                                         a_info[o_ptr->name1].cur_num = 1;
1252                                 }
1253                         }
1254
1255                         place_quest_monsters();
1256
1257                         /* Place some random monsters */
1258                         alloc_times = absence_ticks / alloc_chance;
1259
1260                         if (randint0(alloc_chance) < (absence_ticks % alloc_chance))
1261                                 alloc_times++;
1262
1263                         for (i = 0; i < alloc_times; i++)
1264                         {
1265                                 /* Make a (group of) new monster */
1266                                 (void)alloc_monster(0, 0);
1267                         }
1268                 }
1269
1270                 /* New floor_id or failed to restore */
1271                 else /* if (!loaded) */
1272                 {
1273                         if (sf_ptr->last_visit)
1274                         {
1275                                 /* Temporal file is broken? */
1276 #ifdef JP
1277                                 msg_print("³¬ÃʤϹԤ­»ß¤Þ¤ê¤À¤Ã¤¿¡£");
1278 #else
1279                                 msg_print("The staircases come to a dead end...");
1280 #endif
1281
1282                                 /* Create simple dead end */
1283                                 build_dead_end();
1284
1285                                 /* Break connection */
1286                                 if (change_floor_mode & CFM_UP)
1287                                 {
1288                                         sf_ptr->upper_floor_id = 0;
1289                                 }
1290                                 else if (change_floor_mode & CFM_DOWN)
1291                                 {
1292                                         sf_ptr->lower_floor_id = 0;
1293                                 }
1294                         }
1295                         else
1296                         {
1297                                 /* Newly create cave */
1298                                 generate_cave();
1299                         }
1300
1301                         /* Record last visit turn */
1302                         sf_ptr->last_visit = turn;
1303
1304                         /* Set correct dun_level value */
1305                         sf_ptr->dun_level = dun_level;
1306
1307                         /* Create connected stairs */
1308                         if (!(change_floor_mode & CFM_NO_RETURN))
1309                         {
1310                                 /* Extract stair position */
1311                                 cave_type *c_ptr = &cave[py][px];
1312
1313                                 /*** Create connected stairs ***/
1314
1315                                 /* No stairs down from Quest */
1316                                 if ((change_floor_mode & CFM_UP) && !quest_number(dun_level))
1317                                 {
1318                                         if (change_floor_mode & CFM_SHAFT)
1319                                                 c_ptr->feat = FEAT_MORE_MORE;
1320                                         else
1321                                                 c_ptr->feat = FEAT_MORE;
1322                                 }
1323
1324                                 /* No stairs up when ironman_downward */
1325                                 else if ((change_floor_mode & CFM_DOWN) && !ironman_downward)
1326                                 {
1327                                         if (change_floor_mode & CFM_SHAFT)
1328                                                 c_ptr->feat = FEAT_LESS_LESS;
1329                                         else
1330                                                 c_ptr->feat = FEAT_LESS;
1331                                 }
1332
1333                                 /* Paranoia -- Clear mimic */
1334                                 c_ptr->mimic = 0;
1335
1336                                 /* Connect to previous floor */
1337                                 c_ptr->special = p_ptr->floor_id;
1338                         }
1339                 }
1340
1341                 /* Arrive at random grid */
1342                 if (change_floor_mode & (CFM_RAND_PLACE))
1343                 {
1344                         (void)new_player_spot();
1345                 }
1346
1347                 /* You see stairs blocked */
1348                 else if ((change_floor_mode & CFM_NO_RETURN) &&
1349                          (change_floor_mode & (CFM_DOWN | CFM_UP)))
1350                 {
1351                         if (!p_ptr->blind)
1352                         {
1353 #ifdef JP
1354                                 msg_print("ÆÍÁ³³¬Ãʤ¬ºÉ¤¬¤ì¤Æ¤·¤Þ¤Ã¤¿¡£");
1355 #else
1356                                 msg_print("Suddenly the stairs is blocked!");
1357 #endif
1358                         }
1359                         else
1360                         {
1361 #ifdef JP
1362                                 msg_print("¥´¥È¥´¥È¤È²¿¤«²»¤¬¤·¤¿¡£");
1363 #else
1364                                 msg_print("You hear some noises.");
1365 #endif
1366                         }
1367                 }
1368
1369                 /*
1370                  * Update visit mark
1371                  *
1372                  * The "turn" is not always different number because
1373                  * the level teleport doesn't take any turn.  Use
1374                  * visit mark instead of last visit turn to find the
1375                  * oldest saved floor.
1376                  */
1377                 sf_ptr->visit_mark = latest_visit_mark++;
1378         }
1379
1380         /* Place preserved pet monsters */
1381         place_pet();
1382
1383         /* Hack -- maintain unique and artifacts */
1384         update_unique_artifact(new_floor_id);
1385
1386         /* Now the player is in new floor */
1387         p_ptr->floor_id = new_floor_id;
1388
1389         /* The dungeon is ready */
1390         character_dungeon = TRUE;
1391
1392         /* Hack -- Munchkin characters always get whole map */
1393         if (p_ptr->pseikaku == SEIKAKU_MUNCHKIN)
1394                 wiz_lite((bool)(p_ptr->pclass == CLASS_NINJA));
1395
1396         /* Remember when this level was "created" */
1397         old_turn = turn;
1398
1399         /* No dungeon feeling yet */
1400         p_ptr->feeling_turn = old_turn;
1401         p_ptr->feeling = 0;
1402
1403         /* Clear all flags */
1404         change_floor_mode = 0L;
1405 }
1406
1407
1408
1409 /*
1410  * Create stairs at or move previously created stairs into the player
1411  * location.
1412  */
1413 void stair_creation(void)
1414 {
1415         saved_floor_type *sf_ptr;
1416         saved_floor_type *dest_sf_ptr;
1417
1418         bool up = TRUE;
1419         bool down = TRUE;
1420         s16b dest_floor_id = 0;
1421
1422
1423         /* Forbid up staircases on Ironman mode */
1424         if (ironman_downward) up = FALSE;
1425
1426         /* Forbid down staircases on quest level */
1427         if (quest_number(dun_level) || (dun_level >= d_info[dungeon_type].maxdepth)) down = FALSE;
1428
1429         /* No effect out of standard dungeon floor */
1430         if (!dun_level || (!up && !down) ||
1431             (p_ptr->inside_quest && is_fixed_quest_idx(p_ptr->inside_quest)) ||
1432             p_ptr->inside_arena || p_ptr->inside_battle)
1433         {
1434                 /* arena or quest */
1435 #ifdef JP
1436                 msg_print("¸ú²Ì¤¬¤¢¤ê¤Þ¤»¤ó¡ª");
1437 #else
1438                 msg_print("There is no effect!");
1439 #endif
1440                 return;
1441         }
1442
1443         /* Artifacts resists */
1444         if (!cave_valid_bold(py, px))
1445         {
1446 #ifdef JP
1447                 msg_print("¾²¾å¤Î¥¢¥¤¥Æ¥à¤¬¼öʸ¤òÄ·¤ÍÊÖ¤·¤¿¡£");
1448 #else
1449                 msg_print("The object resists the spell.");
1450 #endif
1451
1452                 return;
1453         }
1454
1455         /* Destroy all objects in the grid */
1456         delete_object(py, px);
1457
1458         /* Extract current floor data */
1459         sf_ptr = get_sf_ptr(p_ptr->floor_id);
1460
1461         /* Paranoia */
1462         if (!sf_ptr)
1463         {
1464                 /* No floor id? -- Create now! */
1465                 p_ptr->floor_id = get_new_floor_id();
1466                 sf_ptr = get_sf_ptr(p_ptr->floor_id);
1467         } 
1468
1469         /* Choose randomly */
1470         if (up && down)
1471         {
1472                 if (randint0(100) < 50) up = FALSE;
1473                 else down = FALSE;
1474         }
1475
1476         /* Destination is already fixed */
1477         if (up)
1478         {
1479                 if (sf_ptr->upper_floor_id) dest_floor_id = sf_ptr->upper_floor_id;
1480         }
1481         else
1482         {
1483                 if (sf_ptr->lower_floor_id) dest_floor_id = sf_ptr->lower_floor_id;
1484         }
1485
1486
1487         /* Search old stairs leading to the destination */
1488         if (dest_floor_id)
1489         {
1490                 int x, y;
1491
1492                 for (y = 0; y < cur_hgt; y++)
1493                 {
1494                         for (x = 0; x < cur_wid; x++)
1495                         {
1496                                 cave_type *c_ptr = &cave[y][x];
1497
1498                                 if (!c_ptr->special) continue;
1499                                 if (feat_uses_special(c_ptr->feat)) continue;
1500                                 if (c_ptr->special != dest_floor_id) continue;
1501
1502                                 /* Remove old stairs */
1503                                 c_ptr->special = 0;
1504                                 cave_set_feat(y, x, floor_type[randint0(100)]);
1505                         }
1506                 }
1507         }
1508
1509         /* No old destination -- Get new one now */
1510         else
1511         {
1512                 dest_floor_id = get_new_floor_id();
1513
1514                 /* Fix it */
1515                 if (up)
1516                         sf_ptr->upper_floor_id = dest_floor_id;
1517                 else
1518                         sf_ptr->lower_floor_id = dest_floor_id;
1519         }
1520
1521         /* Extract destination floor data */
1522         dest_sf_ptr = get_sf_ptr(dest_floor_id);
1523
1524
1525         /* Create a staircase */
1526         if (up)
1527         {
1528                 if (dest_sf_ptr->last_visit && dest_sf_ptr->dun_level <= dun_level - 2)
1529                         cave_set_feat(py, px, FEAT_LESS_LESS);
1530                 else
1531                         cave_set_feat(py, px, FEAT_LESS);
1532         }
1533         else
1534         {
1535                 if (dest_sf_ptr->last_visit && dest_sf_ptr->dun_level >= dun_level + 2)
1536                         cave_set_feat(py, px, FEAT_MORE_MORE);
1537                 else
1538                         cave_set_feat(py, px, FEAT_MORE);
1539         }
1540
1541
1542         /* Connect this stairs to the destination */
1543         cave[py][px].special = dest_floor_id;
1544 }