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