OSDN Git Service

[Implement] ウサウサストライカー召喚処理を追加
[hengbandforosx/hengbandosx.git] / src / birth / game-play-initializer.cpp
1 #include "birth/game-play-initializer.h"
2 #include "dungeon/quest.h"
3 #include "floor/floor-util.h"
4 #include "game-option/birth-options.h"
5 #include "game-option/cheat-options.h"
6 #include "info-reader/fixed-map-parser.h"
7 #include "inventory/inventory-slot-types.h"
8 #include "market/arena.h"
9 #include "monster-race/monster-race.h"
10 #include "monster-race/race-flags1.h"
11 #include "monster-race/race-flags7.h"
12 #include "pet/pet-util.h"
13 #include "player-base/player-class.h"
14 #include "player-base/player-race.h"
15 #include "player-info/race-info.h"
16 #include "player-info/race-types.h"
17 #include "player/digestion-processor.h"
18 #include "system/artifact-type-definition.h"
19 #include "system/baseitem-info.h"
20 #include "system/dungeon-info.h"
21 #include "system/floor-type-definition.h"
22 #include "system/item-entity.h"
23 #include "system/monster-race-info.h"
24 #include "system/player-type-definition.h"
25 #include "util/enum-range.h"
26 #include "util/string-processor.h"
27 #include "world/world.h"
28 #include <algorithm>
29 #include <string>
30
31 /*!
32  * @brief ベースアイテム構造体の鑑定済みフラグをリセットする。
33  * @details
34  * 不具合対策で0からリセットする(セーブは0から)
35  */
36 static void reset_baseitem_idenditication_flags()
37 {
38     for (auto &baseitem : baseitems_info) {
39         baseitem.tried = false;
40         baseitem.aware = false;
41     }
42 }
43
44 /*!
45  * @brief プレイヤー構造体の内容を初期値で消去する(名前を除く) / Clear all the global "character" data (without name)
46  * @param player_ptr プレイヤーへの参照ポインタ
47  * @details 少し長いが、これ1つで処理が完結しているので分割は見送る
48  */
49 void player_wipe_without_name(PlayerType *player_ptr)
50 {
51     const std::string backup_name = player_ptr->name;
52     *player_ptr = {};
53
54     // TODO: キャラ作成からゲーム開始までに  current_floor_ptr を参照しなければならない処理は今後整理して外す。
55     player_ptr->current_floor_ptr = &floor_info;
56     //! @todo std::make_shared の配列対応版は C++20 から
57     player_ptr->inventory_list = std::shared_ptr<ItemEntity[]>{ new ItemEntity[INVEN_TOTAL] };
58     for (int i = 0; i < 4; i++) {
59         strcpy(player_ptr->history[i], "");
60     }
61
62     auto &quest_list = QuestList::get_instance();
63     for (auto &[q_idx, quest] : quest_list) {
64         quest.status = QuestStatusType::UNTAKEN;
65         quest.cur_num = 0;
66         quest.max_num = 0;
67         quest.type = QuestKindType::NONE;
68         quest.level = 0;
69         quest.r_idx = MonsterRace::empty_id();
70         quest.complev = 0;
71         quest.comptime = 0;
72     }
73
74     player_ptr->inven_cnt = 0;
75     player_ptr->equip_cnt = 0;
76     for (int i = 0; i < INVEN_TOTAL; i++) {
77         (&player_ptr->inventory_list[i])->wipe();
78     }
79
80     for (auto &[a_idx, artifact] : artifacts_info) {
81         artifact.is_generated = false;
82     }
83
84     reset_baseitem_idenditication_flags();
85     for (auto &[r_idx, r_ref] : monraces_info) {
86         if (!MonsterRace(r_ref.idx).is_valid()) {
87             continue;
88         }
89         r_ref.cur_num = 0;
90         r_ref.max_num = MAX_MONSTER_NUM;
91         if (r_ref.kind_flags.has(MonsterKindType::UNIQUE)) {
92             r_ref.max_num = MAX_UNIQUE_NUM;
93         } else if (r_ref.population_flags.has(MonsterPopulationType::NAZGUL)) {
94             r_ref.max_num = MAX_NAZGUL_NUM;
95         }
96
97         r_ref.r_pkills = 0;
98         r_ref.r_akills = 0;
99     }
100
101     player_ptr->food = PY_FOOD_FULL - 1;
102     if (PlayerClass(player_ptr).equals(PlayerClassType::SORCERER)) {
103         player_ptr->spell_learned1 = player_ptr->spell_learned2 = 0xffffffffL;
104         player_ptr->spell_worked1 = player_ptr->spell_worked2 = 0xffffffffL;
105     } else {
106         player_ptr->spell_learned1 = player_ptr->spell_learned2 = 0L;
107         player_ptr->spell_worked1 = player_ptr->spell_worked2 = 0L;
108     }
109
110     player_ptr->spell_forgotten1 = player_ptr->spell_forgotten2 = 0L;
111     for (int i = 0; i < 64; i++) {
112         player_ptr->spell_order[i] = 99;
113     }
114
115     player_ptr->learned_spells = 0;
116     player_ptr->add_spells = 0;
117     player_ptr->knowledge = 0;
118     player_ptr->mutant_regenerate_mod = 100;
119
120     cheat_peek = false;
121     cheat_hear = false;
122     cheat_room = false;
123     cheat_xtra = false;
124     cheat_know = false;
125     cheat_live = false;
126     cheat_save = false;
127     cheat_diary_output = false;
128     cheat_turn = false;
129     cheat_immortal = false;
130
131     w_ptr->total_winner = false;
132     player_ptr->timewalk = false;
133     player_ptr->panic_save = 0;
134
135     w_ptr->noscore = 0;
136     w_ptr->wizard = false;
137     player_ptr->wait_report_score = false;
138     player_ptr->pet_follow_distance = PET_FOLLOW_DIST;
139     player_ptr->pet_extra_flags = (PF_TELEPORT | PF_ATTACK_SPELL | PF_SUMMON_SPELL);
140
141     for (const auto &d_ref : dungeons_info) {
142         max_dlv[d_ref.idx] = 0;
143     }
144
145     player_ptr->visit = 1;
146     player_ptr->wild_mode = false;
147
148     player_ptr->max_plv = player_ptr->lev = 1;
149     player_ptr->arena_number = 0;
150     w_ptr->set_arena(true);
151     player_ptr->knows_daily_bounty = false;
152     update_gambling_monsters(player_ptr);
153     player_ptr->muta.clear();
154
155     for (int i = 0; i < 8; i++) {
156         player_ptr->virtues[i] = 0;
157     }
158
159     if (vanilla_town || ironman_downward) {
160         player_ptr->recall_dungeon = DUNGEON_ANGBAND;
161     } else {
162         player_ptr->recall_dungeon = DUNGEON_GALGALS;
163     }
164
165     std::copy_n(backup_name.begin(), backup_name.length(), player_ptr->name);
166 }
167
168 /*!
169  * @brief ダンジョン内部のクエストを初期化する / Initialize random quests and final quests
170  * @param player_ptr プレイヤーへの参照ポインタ
171  */
172 void init_dungeon_quests(PlayerType *player_ptr)
173 {
174     init_flags = INIT_ASSIGN;
175     auto *floor_ptr = player_ptr->current_floor_ptr;
176     auto &quest_list = QuestList::get_instance();
177     floor_ptr->quest_number = QuestId::RANDOM_QUEST1;
178     parse_fixed_map(player_ptr, QUEST_DEFINITION_LIST, 0, 0, 0, 0);
179     floor_ptr->quest_number = QuestId::NONE;
180     for (auto q_idx : EnumRange(QuestId::RANDOM_QUEST1, QuestId::RANDOM_QUEST10)) {
181         auto *q_ptr = &quest_list[q_idx];
182         MonsterRaceInfo *quest_r_ptr;
183         q_ptr->status = QuestStatusType::TAKEN;
184         determine_random_questor(player_ptr, q_ptr);
185         quest_r_ptr = &monraces_info[q_ptr->r_idx];
186         quest_r_ptr->misc_flags.set(MonsterMiscType::QUESTOR);
187         q_ptr->max_num = 1;
188     }
189
190     init_flags = INIT_ASSIGN;
191     floor_ptr->quest_number = QuestId::OBERON;
192     parse_fixed_map(player_ptr, QUEST_DEFINITION_LIST, 0, 0, 0, 0);
193     quest_list[QuestId::OBERON].status = QuestStatusType::TAKEN;
194
195     floor_ptr->quest_number = QuestId::SERPENT;
196     parse_fixed_map(player_ptr, QUEST_DEFINITION_LIST, 0, 0, 0, 0);
197     quest_list[QuestId::SERPENT].status = QuestStatusType::TAKEN;
198     floor_ptr->quest_number = QuestId::NONE;
199 }
200
201 /*!
202  * @brief ゲームターンを初期化する / Reset turn
203  * @param player_ptr プレイヤーへの参照ポインタ
204  * @details アンデッド系種族は開始時刻を夜からにする / Undead start just sunset
205  * @details
206  */
207 void init_turn(PlayerType *player_ptr)
208 {
209     if (PlayerRace(player_ptr).life() == PlayerRaceLifeType::UNDEAD) {
210         w_ptr->game_turn = (TURNS_PER_TICK * 3 * TOWN_DAWN) / 4 + 1;
211         w_ptr->game_turn_limit = TURNS_PER_TICK * TOWN_DAWN * MAX_DAYS + TURNS_PER_TICK * TOWN_DAWN * 3 / 4;
212     } else {
213         w_ptr->game_turn = 1;
214         w_ptr->game_turn_limit = TURNS_PER_TICK * TOWN_DAWN * (MAX_DAYS - 1) + TURNS_PER_TICK * TOWN_DAWN * 3 / 4;
215     }
216
217     w_ptr->dungeon_turn = 1;
218     w_ptr->dungeon_turn_limit = TURNS_PER_TICK * TOWN_DAWN * (MAX_DAYS - 1) + TURNS_PER_TICK * TOWN_DAWN * 3 / 4;
219 }