1 /*
2 * Seven Kingdoms: Ancient Adversaries
3 *
4 * Copyright 1997,1998 Enlight Software Ltd.
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, see <http://www.gnu.org/licenses/>.
18 *
19 */
20
21 // Filename : OW_ROCK.CPP
22 // Description : generate random rock on map
23
24
25 #include <OWORLD.h>
26 #include <OROCKRES.h>
27 #include <OROCK.h>
28 #include <OTERRAIN.h>
29
30
31 //--------------- begin of function World::can_add_rock ----------//
can_add_rock(short x1,short y1,short x2,short y2)32 int World::can_add_rock(short x1, short y1, short x2, short y2)
33 {
34 int x,y;
35 err_when(x1 > x2 || y1 > y2);
36 for(y = y1; y <= y2; ++y)
37 for( x = x1; x <= x2; ++x)
38 if( !get_loc(x,y)->can_add_rock(3) )
39 return 0;
40 return 1;
41 }
42 //--------------- end of function World::can_add_rock ----------//
43
44
45 // --------- begin of function World::add_rock ----------//
46 //
47 // note : make sure the location in the area is free
48 //
add_rock(short rockRecno,short x1,short y1)49 void World::add_rock(short rockRecno, short x1, short y1)
50 {
51 // ------- get the delay remain count for the first frame -----//
52 Rock newRock(rockRecno, x1, y1);
53 int rockArrayRecno = rock_array.add(&newRock);
54 RockInfo *rockInfo = rock_res.get_rock_info(rockRecno);
55
56 for( short dy = 0; dy < rockInfo->loc_height && y1+dy < max_y_loc; ++dy)
57 {
58 for( short dx = 0; dx < rockInfo->loc_width && x1+dx < max_x_loc; ++dx)
59 {
60 short rockBlockRecno = rock_res.locate_block(rockRecno, dx, dy);
61 if( rockBlockRecno )
62 {
63 Location *locPtr = get_loc(x1+dx, y1+dy);
64 err_when( !locPtr->can_add_rock(3) );
65 locPtr->set_rock(rockArrayRecno);
66 locPtr->set_power_off();
67 set_surr_power_off(x1, y1);
68 }
69 }
70 }
71 }
72 // --------- end of function World::add_rock ----------//
73
74
75 // --------- begin of function World::gen_rocks ----------//
gen_rocks(int nGrouped,int nLarge,int nSmall)76 void World::gen_rocks(int nGrouped, int nLarge, int nSmall)
77 {
78 // one 'large' (size 1 to 4) at the center
79 // and a number 'small' (size 1 to 2) at the surroundings
80
81 const int GAP=4;
82 const int HUGE_ROCK_SIZE=6;
83 const int LARGE_ROCK_SIZE=4;
84 const int SMALL_ROCK_SIZE=2;
85
86 int trial = (nGrouped + nLarge + nSmall) * 2;
87
88 while( (nGrouped > 0 || nLarge > 0 || nSmall > 0) && --trial > 0)
89 {
90 // generate grouped rocks
91 if( nGrouped > 0 )
92 {
93 short x = (GAP+SMALL_ROCK_SIZE)+misc.random( max_x_loc - LARGE_ROCK_SIZE +1 - 2*(GAP+SMALL_ROCK_SIZE));
94 short y = (GAP+SMALL_ROCK_SIZE)+misc.random( max_y_loc - LARGE_ROCK_SIZE +1 - 2*(GAP+SMALL_ROCK_SIZE));
95 short x2 = x + LARGE_ROCK_SIZE -1;
96 short y2 = y + LARGE_ROCK_SIZE -1;
97
98 if( can_add_rock(x,y, x2,y2) )
99 {
100 short rockRecno = rock_res.search("R", 1,LARGE_ROCK_SIZE,1,LARGE_ROCK_SIZE,-1,0,
101 terrain_res[get_loc(x,y)->terrain_id]->average_type );
102 if( !rockRecno )
103 continue;
104
105 RockInfo *rockInfo = rock_res.get_rock_info(rockRecno);
106 x2 = x + rockInfo->loc_width - 1;
107 y2 = y + rockInfo->loc_height -1;
108 if( rockInfo->valid_terrain(terrain_res[get_loc(x2, y)->terrain_id]->average_type)
109 && rockInfo->valid_terrain(terrain_res[get_loc(x, y2)->terrain_id]->average_type)
110 && rockInfo->valid_terrain(terrain_res[get_loc(x2,y2)->terrain_id]->average_type))
111 {
112 add_rock(rockRecno, x, y);
113
114 // add other smaller rock
115 for(int subTrial = misc.random(14); subTrial > 0 ; --subTrial)
116 {
117 // sx from x-SMALL_ROCK_SIZE to x+4-1+SMALL_ROCK_SIZE
118 short sx = x - SMALL_ROCK_SIZE - GAP + misc.random( LARGE_ROCK_SIZE + SMALL_ROCK_SIZE + 2*GAP);
119 short sy = y - SMALL_ROCK_SIZE - GAP + misc.random( LARGE_ROCK_SIZE + SMALL_ROCK_SIZE + 2*GAP);
120 short sx2 = sx + SMALL_ROCK_SIZE-1;
121 short sy2 = sy + SMALL_ROCK_SIZE-1;
122
123 if( can_add_rock( sx, sy, sx2, sy2))
124 {
125 short rock2Recno = rock_res.search("R", 1,SMALL_ROCK_SIZE,1,SMALL_ROCK_SIZE,-1,0,
126 terrain_res[get_loc(sx,sy)->terrain_id]->average_type );
127 if(!rock2Recno)
128 continue;
129
130 RockInfo *rock2Info = rock_res.get_rock_info(rock2Recno);
131 sx2 = sx + rock2Info->loc_width -1;
132 sy2 = sy + rock2Info->loc_height -1;
133 if( rock2Info->valid_terrain(terrain_res[get_loc(sx2,sy)->terrain_id]->average_type)
134 && rock2Info->valid_terrain(terrain_res[get_loc(sx,sy2)->terrain_id]->average_type)
135 && rock2Info->valid_terrain(terrain_res[get_loc(sx2,sy2)->terrain_id]->average_type) )
136 {
137 add_rock(rock2Recno, sx, sy);
138 }
139 }
140 }
141 nGrouped--;
142 }
143 }
144 }
145
146 // generate stand-alone large rock
147 if( nLarge > 0 )
148 {
149 short x = misc.random( max_x_loc - HUGE_ROCK_SIZE);
150 short y = misc.random( max_y_loc - HUGE_ROCK_SIZE);
151 short x2 = x + HUGE_ROCK_SIZE -1;
152 short y2 = y + HUGE_ROCK_SIZE -1;
153
154 if( can_add_rock( x, y, x2, y2) )
155 {
156 short rockRecno = rock_res.search("R", SMALL_ROCK_SIZE+1,HUGE_ROCK_SIZE,LARGE_ROCK_SIZE+1,HUGE_ROCK_SIZE,-1,0,
157 terrain_res[get_loc(x,y)->terrain_id]->average_type );
158 if( !rockRecno )
159 continue;
160
161 RockInfo *rockInfo = rock_res.get_rock_info(rockRecno);
162 x2 = x + rockInfo->loc_width - 1;
163 y2 = y + rockInfo->loc_height -1;
164 if( rockInfo->valid_terrain(terrain_res[get_loc(x2, y)->terrain_id]->average_type)
165 && rockInfo->valid_terrain(terrain_res[get_loc(x, y2)->terrain_id]->average_type)
166 && rockInfo->valid_terrain(terrain_res[get_loc(x2,y2)->terrain_id]->average_type))
167 {
168 add_rock(rockRecno, x, y);
169 nLarge--;
170 }
171 }
172 }
173
174 // generate stand-alone small rock
175 if( nSmall > 0)
176 {
177 short x = misc.random( max_x_loc - SMALL_ROCK_SIZE);
178 short y = misc.random( max_y_loc - SMALL_ROCK_SIZE);
179 short x2 = x + SMALL_ROCK_SIZE -1;
180 short y2 = y + SMALL_ROCK_SIZE -1;
181
182 if( can_add_rock( x, y, x2, y2) )
183 {
184 short rockRecno = rock_res.search("R", 1,SMALL_ROCK_SIZE,1,SMALL_ROCK_SIZE,-1,0,
185 terrain_res[get_loc(x,y)->terrain_id]->average_type );
186 if( !rockRecno )
187 continue;
188
189 RockInfo *rockInfo = rock_res.get_rock_info(rockRecno);
190 x2 = x + rockInfo->loc_width - 1;
191 y2 = y + rockInfo->loc_height -1;
192 if( rockInfo->valid_terrain(terrain_res[get_loc(x2, y)->terrain_id]->average_type)
193 && rockInfo->valid_terrain(terrain_res[get_loc(x, y2)->terrain_id]->average_type)
194 && rockInfo->valid_terrain(terrain_res[get_loc(x2,y2)->terrain_id]->average_type))
195 {
196 add_rock(rockRecno, x, y);
197 nSmall--;
198 }
199 }
200 }
201 }
202 }
203 // --------- end of function World::gen_rocks ----------//
204
205
206 //--------------- begin of function World::can_add_dirt ----------//
can_add_dirt(short x1,short y1,short x2,short y2)207 int World::can_add_dirt(short x1, short y1, short x2, short y2)
208 {
209 int x,y;
210 err_when(x1 > x2 || y1 > y2);
211 for(y = y1; y <= y2; ++y)
212 for( x = x1; x <= x2; ++x)
213 if( !get_loc(x,y)->can_add_dirt() )
214 return 0;
215 return 1;
216 }
217 //--------------- end of function World::can_add_dirt ----------//
218
219
220 // --------- begin of function World::add_dirt ----------//
221 //
222 // note : make sure the location in the area is free
223 //
add_dirt(short dirtRecno,short x1,short y1)224 void World::add_dirt(short dirtRecno, short x1, short y1)
225 {
226 if( dirt_array.size() >= 255 )
227 return;
228
229 // ------- get the delay remain count for the first frame -----//
230 Rock newDirt(dirtRecno, x1, y1);
231 int dirtArrayRecno = dirt_array.add(&newDirt);
232
233 if( dirtArrayRecno >= 255) // Location::extra_para is only BYTE
234 return;
235
236 RockInfo *dirtInfo = rock_res.get_rock_info(dirtRecno);
237
238 for( short dy = 0; dy < dirtInfo->loc_height && y1+dy < max_y_loc; ++dy)
239 {
240 for( short dx = 0; dx < dirtInfo->loc_width && x1+dx < max_x_loc; ++dx)
241 {
242 short dirtBlockRecno = rock_res.locate_block(dirtRecno, dx, dy);
243 if( dirtBlockRecno )
244 {
245 Location *locPtr = get_loc(x1+dx, y1+dy);
246 err_when( !locPtr->can_add_dirt() );
247 locPtr->set_dirt(dirtArrayRecno);
248
249 if( dirtInfo->rock_type == DIRT_BLOCKING_TYPE )
250 locPtr->walkable_off();
251 }
252 }
253 }
254 }
255 // --------- end of function World::add_rock ----------//
256
257
258 // --------- begin of function World::gen_dirt ----------//
gen_dirt(int nGrouped,int nLarge,int nSmall)259 void World::gen_dirt(int nGrouped, int nLarge, int nSmall)
260 {
261 // one 'large' (size 1 to 4) at the center
262 // and a number 'small' (size 1 to 2) at the surroundings
263
264 const int GAP=4;
265 const int HUGE_ROCK_SIZE=6;
266 const int LARGE_ROCK_SIZE=4;
267 const int SMALL_ROCK_SIZE=2;
268
269 int trial = (nGrouped + nLarge + nSmall) * 2;
270
271 while( (nGrouped > 0 || nLarge > 0 || nSmall > 0) && --trial > 0)
272 {
273 // generate grouped dirt
274 if( nGrouped > 0 )
275 {
276 short x = (GAP+SMALL_ROCK_SIZE)+misc.random( max_x_loc - LARGE_ROCK_SIZE +1 - 2*(GAP+SMALL_ROCK_SIZE));
277 short y = (GAP+SMALL_ROCK_SIZE)+misc.random( max_y_loc - LARGE_ROCK_SIZE +1 - 2*(GAP+SMALL_ROCK_SIZE));
278 short x2 = x + LARGE_ROCK_SIZE -1;
279 short y2 = y + LARGE_ROCK_SIZE -1;
280
281 if( can_add_dirt(x,y, x2,y2) )
282 {
283 short rockRecno = rock_res.search("DE", 1,LARGE_ROCK_SIZE,1,LARGE_ROCK_SIZE,-1,0,
284 terrain_res[get_loc(x,y)->terrain_id]->average_type );
285 if( !rockRecno )
286 continue;
287
288 RockInfo *rockInfo = rock_res.get_rock_info(rockRecno);
289 x2 = x + rockInfo->loc_width - 1;
290 y2 = y + rockInfo->loc_height -1;
291 if( rockInfo->valid_terrain(terrain_res[get_loc(x2, y)->terrain_id]->average_type)
292 && rockInfo->valid_terrain(terrain_res[get_loc(x, y2)->terrain_id]->average_type)
293 && rockInfo->valid_terrain(terrain_res[get_loc(x2,y2)->terrain_id]->average_type))
294 {
295 add_dirt(rockRecno, x, y);
296
297 // add other smaller rock
298 for(int subTrial = misc.random(14); subTrial > 0 ; --subTrial)
299 {
300 // sx from x-SMALL_ROCK_SIZE to x+4-1+SMALL_ROCK_SIZE
301 short sx = x - SMALL_ROCK_SIZE - GAP + misc.random( LARGE_ROCK_SIZE + SMALL_ROCK_SIZE + 2*GAP);
302 short sy = y - SMALL_ROCK_SIZE - GAP + misc.random( LARGE_ROCK_SIZE + SMALL_ROCK_SIZE + 2*GAP);
303 short sx2 = sx + SMALL_ROCK_SIZE-1;
304 short sy2 = sy + SMALL_ROCK_SIZE-1;
305
306 if( can_add_dirt( sx, sy, sx2, sy2))
307 {
308 short rock2Recno = rock_res.search("DE", 1,SMALL_ROCK_SIZE,1,SMALL_ROCK_SIZE,-1,0,
309 terrain_res[get_loc(sx,sy)->terrain_id]->average_type );
310 if(!rock2Recno)
311 continue;
312
313 RockInfo *rock2Info = rock_res.get_rock_info(rock2Recno);
314 sx2 = sx + rock2Info->loc_width -1;
315 sy2 = sy + rock2Info->loc_height -1;
316 if( rock2Info->valid_terrain(terrain_res[get_loc(sx2,sy)->terrain_id]->average_type)
317 && rock2Info->valid_terrain(terrain_res[get_loc(sx,sy2)->terrain_id]->average_type)
318 && rock2Info->valid_terrain(terrain_res[get_loc(sx2,sy2)->terrain_id]->average_type) )
319 {
320 add_dirt(rock2Recno, sx, sy);
321 }
322 }
323 }
324 nGrouped--;
325 }
326 }
327 }
328
329 // generate stand-alone large dirt
330 if( nLarge > 0 )
331 {
332 short x = misc.random( max_x_loc - HUGE_ROCK_SIZE);
333 short y = misc.random( max_y_loc - HUGE_ROCK_SIZE);
334 short x2 = x + HUGE_ROCK_SIZE -1;
335 short y2 = y + HUGE_ROCK_SIZE -1;
336
337 if( can_add_dirt( x, y, x2, y2) )
338 {
339 short rockRecno = rock_res.search("DE", SMALL_ROCK_SIZE+1,HUGE_ROCK_SIZE,SMALL_ROCK_SIZE+1,HUGE_ROCK_SIZE,-1,0,
340 terrain_res[get_loc(x,y)->terrain_id]->average_type );
341 if( !rockRecno )
342 continue;
343
344 RockInfo *rockInfo = rock_res.get_rock_info(rockRecno);
345 x2 = x + rockInfo->loc_width - 1;
346 y2 = y + rockInfo->loc_height -1;
347 if( rockInfo->valid_terrain(terrain_res[get_loc(x2, y)->terrain_id]->average_type)
348 && rockInfo->valid_terrain(terrain_res[get_loc(x, y2)->terrain_id]->average_type)
349 && rockInfo->valid_terrain(terrain_res[get_loc(x2,y2)->terrain_id]->average_type))
350 {
351 add_dirt(rockRecno, x, y);
352 nLarge--;
353 }
354 }
355 }
356
357 // generate stand-alone small dirt
358 if( nSmall > 0 )
359 {
360 short x = misc.random( max_x_loc - SMALL_ROCK_SIZE);
361 short y = misc.random( max_y_loc - SMALL_ROCK_SIZE);
362 short x2 = x + SMALL_ROCK_SIZE -1;
363 short y2 = y + SMALL_ROCK_SIZE -1;
364
365 if( can_add_dirt( x, y, x2, y2) )
366 {
367 short rockRecno = rock_res.search("DE", 1,SMALL_ROCK_SIZE,1,SMALL_ROCK_SIZE,-1,0,
368 terrain_res[get_loc(x,y)->terrain_id]->average_type );
369 if( !rockRecno )
370 continue;
371
372 RockInfo *rockInfo = rock_res.get_rock_info(rockRecno);
373 x2 = x + rockInfo->loc_width - 1;
374 y2 = y + rockInfo->loc_height -1;
375 if( rockInfo->valid_terrain(terrain_res[get_loc(x2, y)->terrain_id]->average_type)
376 && rockInfo->valid_terrain(terrain_res[get_loc(x, y2)->terrain_id]->average_type)
377 && rockInfo->valid_terrain(terrain_res[get_loc(x2,y2)->terrain_id]->average_type))
378 {
379 add_dirt(rockRecno, x, y);
380 nSmall--;
381 }
382 }
383 }
384 }
385 }
386 // --------- end of function World::gen_dirt ----------//
387