moved almost all hardcoded constants to "define.dat"
[k8-i-v-a-n.git] / src / game / dungeon.cpp
blob6bdb5b6ec43d5f331ead88675786dc90211b3252
1 /*
3 * Iter Vehemens ad Necem (IVAN)
4 * Copyright (C) Timo Kiviluoto
5 * Released under the GNU General
6 * Public License
8 * See LICENSING which should be included
9 * along with this file for more details
12 #include "dungeon.h"
13 #include "level.h"
14 #include "script.h"
15 #include "feerror.h"
16 #include "game.h"
17 #include "fesave.h"
18 #include "feparse.h"
19 #include "femath.h"
20 #include "bitmap.h"
21 #include "iconf.h"
24 dungeon::dungeon () {
28 dungeon::dungeon(int Index) : Index(Index) {
29 Initialize();
30 for (int c = 0; c < GetLevels(); ++c) Generated[c] = false;
34 dungeon::~dungeon () {
35 for (int c = 0; c < GetLevels(); ++c) delete Level[c];
36 delete [] Level;
37 delete [] Generated;
41 void dungeon::Initialize () {
42 std::map<int, dungeonscript>::const_iterator DungeonIterator = game::GetGameScript()->GetDungeon().find(Index);
43 if (DungeonIterator != game::GetGameScript()->GetDungeon().end()) {
44 DungeonScript = &DungeonIterator->second;
45 } else {
46 ABORT("Unknown dungeon #%d requested!", int(Index));
47 return;
49 Level = new level *[GetLevels()];
50 Generated = new truth[GetLevels()];
51 for (int c = 0; c < GetLevels(); ++c) Level[c] = 0;
55 const levelscript *dungeon::GetLevelScript (int I) {
56 std::map<int, levelscript>::const_iterator LevelIterator = DungeonScript->GetLevel().find(I);
57 const levelscript *LevelScript;
58 if (LevelIterator != DungeonScript->GetLevel().end()) LevelScript = &LevelIterator->second;
59 else LevelScript = DungeonScript->GetLevelDefault();
60 return LevelScript;
64 /* Returns whether the level has been visited before */
65 truth dungeon::PrepareLevel (int Index, truth Visual) {
66 if (Generated[Index]) {
67 level *NewLevel = LoadLevel(game::SaveName(), Index);
68 game::SetCurrentArea(NewLevel);
69 game::SetCurrentLevel(NewLevel);
70 game::SetCurrentLSquareMap(NewLevel->GetMap());
71 return true;
73 truth enterImageShown = false;
74 for (int tries = 100; tries > 0; --tries) {
75 level *NewLevel = Level[Index] = new level;
76 NewLevel->SetDungeon(this);
77 NewLevel->SetIndex(Index);
78 const levelscript *LevelScript = GetLevelScript(Index);
79 NewLevel->SetLevelScript(LevelScript);
80 if (!enterImageShown && Visual) {
81 enterImageShown = true;
82 if (LevelScript->GetEnterImage()) {
83 cbitmap *EnterImage = new bitmap(game::GetGameDir()+"graphics/" + *LevelScript->GetEnterImage());
84 game::SetEnterImage(EnterImage);
85 v2 Displacement = *LevelScript->GetEnterTextDisplacement();
86 game::SetEnterTextDisplacement(Displacement);
87 game::TextScreen(CONST_S("Entering ")+GetLevelDescription(Index)+CONST_S("...\n\nThis may take some time, please wait."), Displacement, WHITE, false, true, &game::BusyAnimation);
88 game::TextScreen(CONST_S("Entering ")+GetLevelDescription(Index)+CONST_S("...\n\nPress any key to continue."), Displacement, WHITE, true, false, &game::BusyAnimation);
89 game::SetEnterImage(0);
90 delete EnterImage;
91 } else {
92 game::TextScreen(CONST_S("Entering ")+GetLevelDescription(Index)+CONST_S("...\n\nThis may take some time, please wait."), ZERO_V2, WHITE, false, true, &game::BusyAnimation);
95 if (!NewLevel->Generate(Index)) {
96 // oops, failed
97 delete NewLevel;
98 Level[Index] = 0;
99 continue;
101 game::SetCurrentLSquareMap(NewLevel->GetMap());
102 Generated[Index] = true;
103 game::BusyAnimation();
104 if (*NewLevel->GetLevelScript()->GenerateMonsters()) NewLevel->GenerateNewMonsters(NewLevel->GetIdealPopulation(), false);
105 return false;
107 ABORT("Oops. Cannot generate level. Something is VERY wrong with level scripts.");
108 return false;
112 void dungeon::SaveLevel (cfestring &SaveName, int Number, truth DeleteAfterwards) {
113 outputfile SaveFile(SaveName+'.'+Index+Number, ivanconfig::GetUseMaximumCompression());
114 SaveFile << Level[Number];
115 if (DeleteAfterwards) {
116 delete Level[Number];
117 Level[Number] = 0;
122 level *dungeon::LoadLevel (cfestring &SaveName, int Number) {
123 inputfile SaveFile(SaveName+'.'+Index+Number);
124 return LoadLevel(SaveFile, Number);
128 void dungeon::Save (outputfile &SaveFile) const {
129 SaveFile << Index << WorldMapPos;
130 for (int c = 0; c < GetLevels(); ++c) SaveFile << Generated[c];
134 void dungeon::Load (inputfile &SaveFile) {
135 SaveFile >> Index >> WorldMapPos;
136 Initialize();
137 for (int c = 0; c < GetLevels(); ++c) SaveFile >> Generated[c];
141 int dungeon::GetLevels () const {
142 return *DungeonScript->GetLevels();
146 festring dungeon::GetLevelDescription (int I) {
147 if (GetLevel(I)->GetLevelScript()->GetDescription()) return *GetLevel(I)->GetLevelScript()->GetDescription();
148 return *DungeonScript->GetDescription()+" level "+(I+1);
152 festring dungeon::GetShortLevelDescription (int I) {
153 if (GetLevel(I)->GetLevelScript()->GetShortDescription()) return *GetLevel(I)->GetLevelScript()->GetShortDescription();
154 return *DungeonScript->GetShortDescription()+" level "+(I+1);
158 outputfile &operator << (outputfile &SaveFile, const dungeon *Dungeon) {
159 if (Dungeon) {
160 SaveFile.Put(1);
161 Dungeon->Save(SaveFile);
162 } else {
163 SaveFile.Put(0);
165 return SaveFile;
169 inputfile &operator >> (inputfile &SaveFile, dungeon *&Dungeon) {
170 if (SaveFile.Get()) {
171 Dungeon = new dungeon;
172 Dungeon->Load(SaveFile);
174 return SaveFile;
178 level *dungeon::LoadLevel (inputfile &SaveFile, int Number) {
179 SaveFile >> Level[Number];
180 Level[Number]->SetDungeon(this);
181 Level[Number]->SetIndex(Number);
182 Level[Number]->SetLevelScript(GetLevelScript(Number));
183 return Level[Number];
187 int dungeon::GetLevelTeleportDestination (int From) const {
188 int To;
189 if (Index == ELPURI_CAVE) {
190 if (RAND_2) {
191 To = From+RAND_2+RAND_2+RAND_2+RAND_2+1;
192 if (To > DARK_LEVEL) To = From;
193 } else {
194 To = From-RAND_2-RAND_2-RAND_2-RAND_2-1;
195 if (To < 0) To = 0;
197 return To;
199 if (Index == UNDER_WATER_TUNNEL) return RAND_N(3);
200 if (Index == ALIEN_VESSEL) return RAND_N(3);
201 return From;