/*! * @brief 現在のフロアを離れるに伴って行なわれる保存処理 * / Maintain quest monsters, mark next floor_id at stairs, save current floor, and prepare to enter next floor. * @return なし */ void leave_floor(void) { cave_type *c_ptr = NULL; feature_type *f_ptr; saved_floor_type *sf_ptr; int quest_r_idx = 0; DUNGEON_IDX i; /* Preserve pets and prepare to take these to next floor */ preserve_pet(); /* Remove all mirrors without explosion */ remove_all_mirrors(FALSE); if (p_ptr->special_defense & NINJA_S_STEALTH) set_superstealth(FALSE); /* New floor is not yet prepared */ new_floor_id = 0; /* Temporary get a floor_id (for Arena) */ if (!p_ptr->floor_id && (change_floor_mode & CFM_SAVE_FLOORS) && !(change_floor_mode & CFM_NO_RETURN)) { /* Get temporal floor_id */ p_ptr->floor_id = get_new_floor_id(); } /* Search the quest monster index */ for (i = 0; i < max_q_idx; i++) { if ((quest[i].status == QUEST_STATUS_TAKEN) && ((quest[i].type == QUEST_TYPE_KILL_LEVEL) || (quest[i].type == QUEST_TYPE_RANDOM)) && (quest[i].level == dun_level) && (dungeon_type == quest[i].dungeon) && !(quest[i].flags & QUEST_FLAG_PRESET)) { quest_r_idx = quest[i].r_idx; } } /* Maintain quest monsters */ for (i = 1; i < m_max; i++) { monster_race *r_ptr; monster_type *m_ptr = &m_list[i]; /* Skip dead monsters */ if (!m_ptr->r_idx) continue; /* Only maintain quest monsters */ if (quest_r_idx != m_ptr->r_idx) continue; /* Extract real monster race */ r_ptr = real_r_ptr(m_ptr); /* Ignore unique monsters */ if ((r_ptr->flags1 & RF1_UNIQUE) || (r_ptr->flags7 & RF7_NAZGUL)) continue; /* Delete non-unique quest monsters */ delete_monster_idx(i); } /* Check if there is a same item */ for (i = 0; i < INVEN_PACK; i++) { object_type *o_ptr = &inventory[i]; /* Skip dead objects */ if (!o_ptr->k_idx) continue; /* Delete old memorized location of the artifact */ if (object_is_fixed_artifact(o_ptr)) { a_info[o_ptr->name1].floor_id = 0; } } /* Extract current floor info or NULL */ sf_ptr = get_sf_ptr(p_ptr->floor_id); /* Choose random stairs */ if ((change_floor_mode & CFM_RAND_CONNECT) && p_ptr->floor_id) { locate_connected_stairs(sf_ptr); } /* Extract new dungeon level */ if (change_floor_mode & CFM_SAVE_FLOORS) { /* Extract stair position */ c_ptr = &cave[p_ptr->y][p_ptr->x]; f_ptr = &f_info[c_ptr->feat]; /* Get back to old saved floor? */ if (c_ptr->special && !have_flag(f_ptr->flags, FF_SPECIAL) && get_sf_ptr(c_ptr->special)) { /* Saved floor is exist. Use it. */ new_floor_id = c_ptr->special; } /* Mark shaft up/down */ if (have_flag(f_ptr->flags, FF_STAIRS) && have_flag(f_ptr->flags, FF_SHAFT)) { prepare_change_floor_mode(CFM_SHAFT); } } /* Climb up/down some sort of stairs */ if (change_floor_mode & (CFM_DOWN | CFM_UP)) { int move_num = 0; /* Extract level movement number */ if (change_floor_mode & CFM_DOWN) move_num = 1; else if (change_floor_mode & CFM_UP) move_num = -1; /* Shafts are deeper than normal stairs */ if (change_floor_mode & CFM_SHAFT) move_num += SGN(move_num); /* Get out from or Enter the dungeon */ if (change_floor_mode & CFM_DOWN) { if (!dun_level) move_num = d_info[dungeon_type].mindepth; } else if (change_floor_mode & CFM_UP) { if (dun_level + move_num < d_info[dungeon_type].mindepth) move_num = -dun_level; } dun_level += move_num; } /* Leaving the dungeon to town */ if (!dun_level && dungeon_type) { p_ptr->leaving_dungeon = TRUE; if (!vanilla_town && !lite_town) { p_ptr->wilderness_y = d_info[dungeon_type].dy; p_ptr->wilderness_x = d_info[dungeon_type].dx; } p_ptr->recall_dungeon = dungeon_type; dungeon_type = 0; /* Reach to the surface -- Clear all saved floors */ change_floor_mode &= ~CFM_SAVE_FLOORS; } /* Kill some old saved floors */ if (!(change_floor_mode & CFM_SAVE_FLOORS)) { /* Kill all saved floors */ for (i = 0; i < MAX_SAVED_FLOORS; i++) kill_saved_floor(&saved_floors[i]); /* Reset visit_mark count */ latest_visit_mark = 1; } else if (change_floor_mode & CFM_NO_RETURN) { /* Kill current floor */ kill_saved_floor(sf_ptr); } /* No current floor -- Left/Enter dungeon etc... */ if (!p_ptr->floor_id) { /* No longer need to save current floor */ return; } /* Mark next floor_id on the previous floor */ if (!new_floor_id) { /* Get new id */ new_floor_id = get_new_floor_id(); /* Connect from here */ if (c_ptr && !feat_uses_special(c_ptr->feat)) { c_ptr->special = new_floor_id; } } /* Fix connection -- level teleportation or trap door */ if (change_floor_mode & CFM_RAND_CONNECT) { if (change_floor_mode & CFM_UP) sf_ptr->upper_floor_id = new_floor_id; else if (change_floor_mode & CFM_DOWN) sf_ptr->lower_floor_id = new_floor_id; } /* If you can return, you need to save previous floor */ if ((change_floor_mode & CFM_SAVE_FLOORS) && !(change_floor_mode & CFM_NO_RETURN)) { /* Get out of the my way! */ get_out_monster(); /* Record the last visit turn of current floor */ sf_ptr->last_visit = turn; /* Forget the lite */ forget_lite(); /* Forget the view */ forget_view(); /* Forget the view */ clear_mon_lite(); /* Save current floor */ if (!save_floor(sf_ptr, 0)) { /* Save failed -- No return */ prepare_change_floor_mode(CFM_NO_RETURN); /* Kill current floor */ kill_saved_floor(get_sf_ptr(p_ptr->floor_id)); } } }
/* * Enter a store, and interact with it. * * Note that we use the standard "request_command()" function * to get a command, allowing us to use "command_arg" and all * command macros and other nifty stuff, but we use the special * "shopping" argument, to force certain commands to be converted * into other commands, normally, we convert "p" (pray) and "m" * (cast magic) into "g" (get), and "s" (search) into "d" (drop). */ void do_cmd_store(void) { s32b which; s32b maintain_num; s32b i; bool recreate = FALSE; store_type *st_ptr; store_info_type *sti_ptr; cave_type *c_ptr; /* Access the player grid */ c_ptr = &cave[p_ptr->py][p_ptr->px]; /* Verify a store */ if (!cave_feat_is(c_ptr, FLAG_CONTAINS_BUILDING)) { msg_print("You see no store here."); return; } /* Extract the store code */ which = get_flag(c_ptr, FLAG_CONTAINS_BUILDING); /* Get the store */ st_ptr = flag_get_store(&town_info[p_ptr->town_num].stores, which); /* If it does not exists yet, create it */ if (!st_ptr) { call_lua("store.create_for_town", "(d,d)", "", p_ptr->town_num, which); st_ptr = flag_get_store(&town_info[p_ptr->town_num].stores, which); if (!st_ptr) quit(format("Could not create store %d town %d! BAD BAD BAD!", which, p_ptr->town_num)); } /* Hack -- Check the "locked doors" */ if (st_ptr->store_open > turn) { msg_print("The doors are locked."); return; } sti_ptr = &st_info[st_ptr->st_idx]; /* Calculate the number of store maintainances since the last visit */ if (has_flag(sti_ptr, FLAG_STORE_MAINTAIN_TURNS)) { if (get_flag(sti_ptr, FLAG_STORE_MAINTAIN_TURNS) >= 1) maintain_num = (turn - st_ptr->last_visit) / (10L * get_flag(sti_ptr, FLAG_STORE_MAINTAIN_TURNS)); else maintain_num = 0; } else maintain_num = (turn - st_ptr->last_visit) / (10L * STORE_TURNS); /* Maintain the store max. 10 times */ if (maintain_num > 10) maintain_num = 10; if (maintain_num) { /* Maintain the store */ for (i = 0; i < maintain_num; i++) call_lua("store.maintain", "(S)", "", st_ptr); /* Save the visit */ st_ptr->last_visit = turn; } /* Forget the lite */ /* forget_lite(); */ /* Forget the view */ forget_view(); call_lua("store.display", "(S)", "", st_ptr); /* Free turn XXX XXX XXX */ energy_use = 0; /* Recreate the level only when needed */ if (recreate) { /* Reinit wilderness to activate quests ... */ p_ptr->oldpx = p_ptr->px; p_ptr->oldpy = p_ptr->py; p_ptr->leaving = TRUE; } /* Hack -- Cancel automatic command */ command_new = 0; /* Hack -- Cancel "see" mode */ command_see = FALSE; /* Flush messages XXX XXX XXX */ msg_print(NULL); /* Clear the screen */ Term_clear(); /* Update everything */ p_ptr->update |= (PU_VIEW | PU_MON_LITE); p_ptr->update |= (PU_MONSTERS); /* Redraw entire screen */ flag_bool(&p_ptr->redraw, FLAG_PR_BASIC); flag_bool(&p_ptr->redraw, FLAG_PR_EXTRA); /* Redraw map */ flag_bool(&p_ptr->redraw, FLAG_PR_MAP); /* Window stuff */ flag_bool(&p_ptr->window, FLAG_PW_OVERHEAD); }
/* * Write the current dungeon (new method) */ static bool wr_dungeon(void) { saved_floor_type *cur_sf_ptr; int i; /* Forget the lite */ forget_lite(); /* Forget the view */ forget_view(); /* Forget the view */ clear_mon_lite(); /* Update lite/view */ p_ptr->update |= (PU_VIEW | PU_LITE | PU_MON_LITE); /* Update monsters */ p_ptr->update |= (PU_MONSTERS | PU_DISTANCE | PU_FLOW); /*** Meta info ***/ /* Number of floor_id used from birth */ wr_s16b(max_floor_id); /* Current dungeon type */ wr_byte(dungeon_type); /*** No saved floor (On the surface etc.) ***/ if (!p_ptr->floor_id) { /* No array elements */ wr_byte(0); /* Write the current floor data */ wr_saved_floor(NULL); /* Success */ return TRUE; } /*** In the dungeon ***/ /* Number of array elements */ wr_byte(MAX_SAVED_FLOORS); /* Write the saved_floors array */ for (i = 0; i < MAX_SAVED_FLOORS; i++) { saved_floor_type *sf_ptr = &saved_floors[i]; wr_s16b(sf_ptr->floor_id); wr_byte(sf_ptr->savefile_id); wr_s16b(sf_ptr->dun_level); wr_s32b(sf_ptr->last_visit); wr_u32b(sf_ptr->visit_mark); wr_s16b(sf_ptr->upper_floor_id); wr_s16b(sf_ptr->lower_floor_id); } /* Extract pointer to current floor */ cur_sf_ptr = get_sf_ptr(p_ptr->floor_id); /* Save current floor to temporal file */ if (!save_floor(cur_sf_ptr, (SLF_SECOND))) return FALSE; /* Move data in temporal files to the savefile */ for (i = 0; i < MAX_SAVED_FLOORS; i++) { saved_floor_type *sf_ptr = &saved_floors[i]; /* Unused element */ if (!sf_ptr->floor_id) continue; /* Load temporal saved floor file */ if (load_floor(sf_ptr, (SLF_SECOND | SLF_NO_KILL))) { /* Mark success */ wr_byte(0); /* Write saved floor data to the save file */ wr_saved_floor(sf_ptr); } else { /* Mark failure */ wr_byte(1); } } /* Restore current floor */ if (!load_floor(cur_sf_ptr, (SLF_SECOND))) return FALSE; /* Success */ return TRUE; }
/* * Handle "p_ptr->update" */ void update_stuff(void) { /* Update stuff */ if (!p_ptr->update) return; if (p_ptr->update & (PU_BONUS)) { p_ptr->update &= ~(PU_BONUS); update_bonuses(); } if (p_ptr->update & (PU_TORCH)) { p_ptr->update &= ~(PU_TORCH); calc_torch(); } if (p_ptr->update & (PU_HP)) { p_ptr->update &= ~(PU_HP); calc_hitpoints(); } if (p_ptr->update & (PU_MANA)) { p_ptr->update &= ~(PU_MANA); calc_mana(); } if (p_ptr->update & (PU_SPELLS)) { p_ptr->update &= ~(PU_SPELLS); calc_spells(); } /* Character is not ready yet, no screen updates */ if (!character_generated) return; /* Character is in "icky" mode, no screen updates */ if (character_icky) return; if (p_ptr->update & (PU_FORGET_VIEW)) { p_ptr->update &= ~(PU_FORGET_VIEW); forget_view(); } if (p_ptr->update & (PU_UPDATE_VIEW)) { p_ptr->update &= ~(PU_UPDATE_VIEW); update_view(); } if (p_ptr->update & (PU_FORGET_FLOW)) { p_ptr->update &= ~(PU_FORGET_FLOW); forget_flow(); } if (p_ptr->update & (PU_UPDATE_FLOW)) { p_ptr->update &= ~(PU_UPDATE_FLOW); update_flow(); } if (p_ptr->update & (PU_DISTANCE)) { p_ptr->update &= ~(PU_DISTANCE); p_ptr->update &= ~(PU_MONSTERS); update_monsters(TRUE); } if (p_ptr->update & (PU_MONSTERS)) { p_ptr->update &= ~(PU_MONSTERS); update_monsters(FALSE); } if (p_ptr->update & (PU_PANEL)) { p_ptr->update &= ~(PU_PANEL); event_signal(EVENT_PLAYERMOVED); } }