1 /*
2 This file is part of "Avanor, the Land of Mystery" roguelike game
3 Home page: http://www.avanor.com/
4 Copyright (C) 2000-2003 Vadim Gaidukevich
5
6 This program is free software; you can redistribute it and/or modify
7 it under the terms of the GNU General Public License as published by
8 the Free Software Foundation; either version 2 of the License, or
9 (at your option) any later version.
10
11 This program is distributed in the hope that it will be useful,
12 but WITHOUT ANY WARRANTY; without even the implied warranty of
13 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
14 GNU General Public License for more details.
15
16 You should have received a copy of the GNU General Public License
17 along with this program; if not, write to the Free Software
18 Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
19 */
20
21 #include "location.h"
22 #include "cbuilder.h"
23 #include "xarchive.h"
24 #include "other_misc.h"
25 #include "item_misc.h"
26 #include "game.h"
27 #include "unique.h"
28
29 int XLocation::rand_location_count = L_RANDOM;
30
31 REGISTER_CLASS(XLocation);
32 REGISTER_CLASS(XMushroomsCaveLocation);
33
XLocation(LOCATION location)34 XLocation::XLocation(LOCATION location)
35 {
36 visited_by_hero = 0;
37 map = NULL; //map will created by XBuilder...
38 for (int i = 0; i < MAX_PLACES; i++)
39 places[i] = NULL;
40
41 assert(Game.locations[location] == NULL);
42 ln = location;
43 Game.locations[location] = this;
44
45 ttmb = 1000000;
46 ttm = ttmb;
47 im = IM_OTHER;
48 }
49
Invalidate()50 void XLocation::Invalidate()
51 {
52 for (int i = 0; i < MAX_PLACES; i++)
53 if (places[i])
54 {
55 places[i]->Invalidate();
56 places[i] = NULL;
57 }
58 delete map; // map must be the last!!!!!
59
60 XObject::Invalidate();
61 }
62
AddPlace(XAnyPlace * pl)63 void XLocation::AddPlace(XAnyPlace * pl)
64 {
65 for (int i = 0; i < MAX_PLACES; i++)
66 if (places[i] == NULL)
67 {
68 places[i] = pl;
69 return;
70 }
71 assert(0);
72 }
73
GetFreeXY(XPoint * pt,XRect * area)74 void XLocation::GetFreeXY(XPoint * pt, XRect * area)
75 {
76 int f = 10000;
77 int tx, ty;
78
79 int bx, by, dx, dy;
80 if (area)
81 {
82 bx = area->left;
83 by = area->top;
84 dx = area->Width();
85 dy = area->Hight();
86 } else
87 {
88 bx = 0;
89 by = 0;
90 dx = map->len;
91 dy = map->hgt;
92 }
93
94 while(f-- > 0)
95 {
96 tx = vRand() % dx + bx;
97 ty = vRand() % dy + by;
98 if (map->XGetMovability(tx, ty) == 0 && map->GetSpecial(tx, ty) == NULL)
99 {
100 pt->x = tx;
101 pt->y = ty;
102 return;
103 }
104 }
105 assert(0);
106 }
107
108
BuildCave()109 void XLocation::BuildCave()
110 {
111 int cl = 80;
112 int ch = 20;
113 map = new XMap(cl, ch);
114
115 for (int i = 0; i < map->hgt; i++)
116 {
117 for (int j = 0; j < map->len; j++)
118 {
119 map->SetXY(j, i, M_MAGMA);
120 }
121 }
122
123 for (int k = 0; k < 150; k++)
124 {
125 int qx = vRand() % (cl - 7) + 1;
126 int qy = vRand() % (ch - 5) + 1;
127
128 for (int q = 0; q < 360; q += 3)
129 {
130 for (int w = 0; w < 3; w++)
131 {
132 int tx = qx + (int)(w * cos(q * M_PI / 180.0));
133 int ty = qy + (int)(w * sin(q * M_PI / 180.0));
134 if (tx > 0 && ty > 0 && tx < 79 && ty < 19)
135 {
136 map->SetXY(tx, ty, M_CAVEFLOOR);
137 }
138 }
139 }
140 }
141 }
142
BuildLabirint(int create_trap_door_chest)143 void XLocation::BuildLabirint(int create_trap_door_chest)
144 {
145 XCaveBuilder * xcb = new XCaveBuilder(this, create_trap_door_chest);
146 xcb->Build();
147 delete xcb;
148 // if (create_trap_door_chest)
149 // {
150 // CreateDoors();
151 // CreateTraps();
152 // CreateChests();
153 // }
154 }
155
156
CreateTraps()157 void XLocation::CreateTraps()
158 {
159 if (vRand(3) == 1)
160 {
161 XPoint pt;
162 for (int i = 0; i < vRand(7); i++)
163 {
164 GetFreeXY(&pt);
165 new XTrap(pt.x, pt.y, this);
166 }
167 }
168 }
169
CreateChests()170 void XLocation::CreateChests()
171 {
172 if (vRand(3) == 1)
173 {
174 XPoint pt;
175 for (int i = 0; i < vRand(4); i++)
176 {
177 GetFreeXY(&pt);
178 XChest * ch1 = new XChest(vRand(6) + 1, IM_ITEM, 1, 5000);
179 ch1->Drop(this, pt.x, pt.y);
180 }
181 }
182 }
183
NewCreature(CREATURE_NAME cn,int x,int y,GROUP_ID gid)184 XCreature * XLocation::NewCreature(CREATURE_NAME cn, int x, int y, GROUP_ID gid)
185 {
186 XCreature * cr = XCreatureStorage::Create(cn);
187 cr->group_id = gid;
188 if (cr->xai->GetAIFlag() & AIF_PEACEFUL)
189 cr->xai->SetEnemyClass(CR_NONE); //by default all creatures in pease with others.
190 Game.NewCreature(cr, x, y, this);
191 return cr;
192 }
193
NewCreature(CREATURE_NAME cn,XRect * rect,GROUP_ID gid,unsigned int ai_flags)194 XCreature * XLocation::NewCreature(CREATURE_NAME cn, XRect * rect, GROUP_ID gid, unsigned int ai_flags)
195 {
196 XPoint pt;
197 GetFreeXY(&pt, rect);
198 XCreature * cr = NewCreature(cn, pt.x, pt.y, gid);
199 if (cr->xai->GetAIFlag() & AIF_PEACEFUL)
200 cr->xai->SetEnemyClass(CR_NONE); //by default all creatures in pease with others.
201 if (rect && (ai_flags & AIF_GUARD_AREA))
202 {
203 cr->xai->SetArea(rect, ln);
204 cr->xai->LearnTraps();
205 }
206 cr->xai->SetAIFlag((AI_FLAG)(ai_flags));
207 return cr;
208 }
209
NewCreature(CREATURE_CLASS crc,XRect * rect,GROUP_ID gid,unsigned int ai_flags)210 XCreature * XLocation::NewCreature(CREATURE_CLASS crc, XRect * rect, GROUP_ID gid, unsigned int ai_flags)
211 {
212 XPoint pt;
213 GetFreeXY(&pt, rect);
214 XCreature * cr = XCreatureStorage::CreateRnd(crc);
215 cr->group_id = gid;
216 if (cr->xai->GetAIFlag() & AIF_PEACEFUL)
217 cr->xai->SetEnemyClass(CR_NONE); //by default all creatures in pease with others.
218 Game.NewCreature(cr, pt.x, pt.y, this);
219 if (rect && (ai_flags & AIF_GUARD_AREA))
220 {
221 cr->xai->SetArea(rect, ln);
222 cr->xai->LearnTraps();
223 }
224 cr->xai->SetAIFlag((AI_FLAG)(ai_flags));
225 return cr;
226 }
227
228
NewWay(LOCATION target_ln,STAIRWAYTYPE s_type,XRect * area)229 XStairWay * XLocation::NewWay(LOCATION target_ln, STAIRWAYTYPE s_type, XRect * area)
230 {
231 XPoint pt;
232 GetFreeXY(&pt, area);
233 return NewWay(pt.x, pt.y, target_ln, s_type);
234 }
235
NewWay(int x,int y,LOCATION target_ln,STAIRWAYTYPE s_type)236 XStairWay * XLocation::NewWay(int x, int y, LOCATION target_ln, STAIRWAYTYPE s_type)
237 {
238 XStairWay * pWay = new XStairWay(x, y, this, target_ln, s_type);
239 ways_list.push_back(pWay);
240 return pWay;
241 }
242
243
244
CreateShop(unsigned int im,XRect * rect,char * sk_name,SHOP_DOOR sd)245 void XLocation::CreateShop(unsigned int im, XRect * rect, char * sk_name, SHOP_DOOR sd)
246 {
247 XShop * shop = new XShop(rect, (ITEM_MASK)im, this, sd);
248 AddPlace(shop);
249 XCreature * cr = NewCreature(CN_SHOPKEEPER, rect);
250 ((XShopkeeper *)cr)->SetShop(sk_name, shop);
251 }
252
GetCreatureCount(unsigned int creature_class)253 int XLocation::GetCreatureCount(unsigned int creature_class)
254 {
255 int count = 0;
256 XObject * o = root;
257 while (o)
258 {
259 if ((o->im & IM_CREATURE) && (((XCreature *)o)->l->xguid == this->xguid) && (((XCreature *)o)->creature_class) & creature_class)
260 count++;
261 o = o->next;
262 }
263 return count;
264 }
265
Store(XFile * f)266 void XLocation::Store(XFile * f)
267 {
268 XObject::Store(f);
269 map->Store(f);
270 for (int i = 0; i < MAX_PLACES; i++) places[i].Store(f);
271 f->Write(brief_name, 10);
272 f->Write(full_name, 80);
273 f->Write(&visited_by_hero);
274 f->Write(&ln, sizeof(LOCATION));
275 }
276
Restore(XFile * f)277 void XLocation::Restore(XFile * f)
278 {
279 XObject::Restore(f);
280 map = new XMap();
281 map->Restore(f);
282 for (int i = 0; i < MAX_PLACES; i++)
283 {
284 places[i].Restore(f);
285 if (places[i] && places[i]->im & IM_WAY)
286 ways_list.push_back(places[i]);
287 }
288 f->Read(brief_name, 10);
289 f->Read(full_name, 80);
290 f->Read(&visited_by_hero);
291 f->Read(&ln, sizeof(LOCATION));
292 }
293
DumpLocation(FILE * f)294 void XLocation::DumpLocation(FILE * f)
295 {
296 fprintf(f, "###### %s ######\n", full_name);
297 map->Dump(f);
298 fprintf(f, "\n");
299 fprintf(f, "\n");
300 }
301
302
CreateRandomCave()303 void XLocation::CreateRandomCave()
304 {
305 int deep = vRand(6) + 5;
306 int view = (vRand(2) == 1);
307 int start_cr_lvl = vRand(CRL_AVG);
308
309 XRect tr(115, 60, 180, 80);
310 Game.locations[L_MAIN]->NewWay((LOCATION)rand_location_count, STW_DOWN, &tr);
311 new XRandomLocation(1, view, L_MAIN, rand_location_count + 1, start_cr_lvl);
312 int i = 1;
313 for (; i < deep - 1; i++)
314 {
315 new XRandomLocation(i + 1, view, rand_location_count - 1, rand_location_count + 1, start_cr_lvl + (1 << i));
316 }
317 new XRandomLocation(i + 1, view, rand_location_count - 1, 0, start_cr_lvl + (1 << i));
318 }
319
320
321
XRandomLocation(int deep,int view,int way_up,int way_down,int cr_lvl)322 XRandomLocation::XRandomLocation(int deep, int view, int way_up, int way_down, int cr_lvl) : XLocation((LOCATION)(XLocation::rand_location_count))
323 {
324 XLocation::rand_location_count++;
325 sprintf(brief_name, "Rnd%d", deep);
326 sprintf(full_name, "Random Place Level %d", deep);
327
328 if (view)
329 BuildCave();
330 else
331 {
332 map = new XMap(80, 20);
333 BuildLabirint(1);
334 }
335
336 XPoint pt;
337 if (way_up)
338 {
339 NewWay((LOCATION)way_up, STW_UP, NULL);
340 }
341
342 if (way_down)
343 {
344 NewWay((LOCATION)way_down, STW_DOWN, NULL);
345 }
346 Game.Scheduler.Add(new XUniversalGen(this, (CREATURE_CLASS)(CR_UNDEAD | CR_BLOB | CR_INSECT | CR_REPTILE | CR_RAT | CR_ALL_IMPL), (CREATURE_LEVEL)cr_lvl, 4, 50000));
347 }
348
349
350