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_WALL.CPP
22 // Description : class World for building wall
23 // Ownership : Gilbert
24
25 #include <OWORLD.h>
26 #include <OMATRIX.h>
27 #include <WALLTILE.h>
28 #include <OWALLRES.h>
29 #include <OTOWN.h>
30 #include <OREMOTE.h>
31 #include <ONATIONA.h>
32
33 #define WALL_GROWTH_RATE 6
34
35 //--------------- begin of function World::can_build_area ----------//
can_build_area(short x1,short y1,short x2,short y2)36 int World::can_build_area(short x1, short y1, short x2, short y2)
37 {
38 int x,y;
39 err_when(x1 > x2 || y1 > y2);
40 for(y = y1; y <= y2; ++y)
41 for( x = x1; x <= x2; ++x)
42 if( ! get_loc(x,y)->can_build_wall())
43 return 0;
44 return 1;
45 }
46 //--------------- end of function World::can_build_area ----------//
47
48 //--------------- begin of function World::build_wall ----------//
build_wall(int townRecno,short initHp)49 void World::build_wall(int townRecno, short initHp)
50 {
51 Town* townPtr = town_array[townRecno];
52
53 int xLoc1 = MAX(0, townPtr->loc_x1-WALL_SPACE_LOC);
54 int yLoc1 = MAX(0, townPtr->loc_y1-WALL_SPACE_LOC);
55 int xLoc2 = MIN(MAX_WORLD_X_LOC-1, townPtr->loc_x2+WALL_SPACE_LOC);
56 int yLoc2 = MIN(MAX_WORLD_Y_LOC-1, townPtr->loc_y2+WALL_SPACE_LOC);
57
58 //--------------- build city wall -------------//
59 build_wall_section(xLoc1, yLoc1, xLoc2, yLoc2, townRecno, initHp);
60 }
61 //--------------- end of function World::build_wall ----------//
62
63 //--------------- begin of function World::build_wall_section ----------//
build_wall_section(short x1,short y1,short x2,short y2,short townRecno,short initHp)64 void World::build_wall_section(short x1, short y1, short x2, short y2,
65 short townRecno, short initHp)
66 {
67 //--------- build west wall -----------//
68 Location *locPtr;
69 short westWallFirst;
70 for( westWallFirst = y1; westWallFirst < y2; ++westWallFirst)
71 {
72 if( get_loc(x1,westWallFirst)->can_build_wall() )
73 {
74 //--------- find place for the west gate ---------//
75 if( x1 >= GATE_WIDTH-1 && y2-y1 >= GATE_LENGTH)
76 {
77 //----- try from the middle, and then butterfly outward ---//
78 short increment = 0;
79 short trial, westGateY;
80 for( trial=y2-y1-GATE_LENGTH, westGateY=y1+(trial+1)/2;
81 trial > 0; --trial, westGateY += increment)
82 {
83 if(can_build_area(x1-GATE_WIDTH+1, westGateY,
84 x1, westGateY+GATE_LENGTH-1) )
85 {
86 //-------- put west gate --------- //
87 build_west_gate(x1-GATE_WIDTH+1, westGateY, townRecno, initHp);
88 break;
89 }
90 increment = -increment;
91 if( increment >= 0)
92 ++increment;
93 else
94 --increment;
95 }
96 //---------- put other wall ----------//
97 build_west_wall(x1, y1, y2, townRecno, initHp);
98
99 //--------- open west gate ----------//
100 open_west_gate(x1, westGateY, townRecno);
101
102 }
103 else
104 {
105 //-------- x1 too small for gate -------//
106 get_loc(x1,westWallFirst)->set_wall(NTOWER, townRecno, initHp);
107 get_loc(x1,westWallFirst)->set_fire_src(-50);
108 }
109 break;
110 }
111 }
112
113
114 //--------- build east wall -----------
115 short eastWallFirst;
116 for( eastWallFirst = y1; eastWallFirst < y2; ++eastWallFirst)
117 {
118 if( get_loc(x2, eastWallFirst)->can_build_wall())
119 {
120 //---------- find place for the gate --------- //
121 if( x2 <= max_x_loc - GATE_WIDTH +1 && y2-y1 >= GATE_LENGTH)
122 {
123 //---- try from the middle, and then butterfly outward ----//
124 short increment = 0;
125 short trial, eastGateY;
126 for( trial=y2-y1-GATE_LENGTH, eastGateY=y1+(trial+1)/2;
127 trial > 0; --trial, eastGateY += increment)
128 {
129 if(can_build_area(x2, eastGateY, x2+GATE_WIDTH-1, eastGateY+GATE_LENGTH-1) )
130 {
131 //----------- put east gate ----------//
132 build_east_gate(x2, eastGateY, townRecno, initHp);
133 break;
134 }
135 increment = -increment;
136 if( increment >= 0)
137 ++increment;
138 else
139 --increment;
140 }
141 //-------- put other wall ---------//
142 build_east_wall(x2, y1, y2, townRecno, initHp);
143
144 //--------- open east gate ----------//
145 open_east_gate(x2, eastGateY, townRecno);
146 }
147 else
148 {
149 //------- x2 too big for gate ---------//
150 get_loc(x2,eastWallFirst)->set_wall(NETOWER, townRecno, initHp);
151 get_loc(x2,eastWallFirst)->set_fire_src(-50);
152 }
153 break;
154 }
155 }
156
157 //--------- build north wall -----------//
158 short northWallFirst;
159 for( northWallFirst = x1; northWallFirst < x2; ++northWallFirst)
160 {
161 if( (locPtr = get_loc(northWallFirst, y1))->can_build_wall() ||
162 ( locPtr->is_wall() && locPtr->wall_town_recno() == townRecno) )
163 {
164 //-------- find place for the north gate --------//
165 if( y1 >= GATE_WIDTH-1 && x2-x1 >= GATE_LENGTH)
166 {
167 //------- try from the middle, and then butterfly outward -------//
168 short increment = 0;
169 short trial, northGateX;
170 for( trial=x2-x1-GATE_LENGTH, northGateX=x1+(trial+1)/2;
171 trial > 0; --trial, northGateX += increment)
172 {
173 if(can_build_area(northGateX, y1-GATE_WIDTH+1,
174 northGateX+GATE_LENGTH-1, y1) )
175 {
176 //--------------- put north gate ----------------//
177 build_north_gate(northGateX, y1-GATE_WIDTH+1, townRecno, initHp);
178 break;
179 }
180 increment = -increment;
181 if( increment >= 0)
182 ++increment;
183 else
184 --increment;
185 }
186 //----------- put other wall --------------//
187 build_north_wall(x1, x2, y1, townRecno, initHp);
188
189 //--------- open north gate ----------//
190 open_north_gate(northGateX, y1, townRecno);
191
192 }
193 else
194 {
195 //------------ y1 too small for gate -----------//
196 if(locPtr->can_build_wall() )
197 {
198 locPtr->set_wall(NTOWER, townRecno, initHp);
199 locPtr->set_fire_src(-50);
200 }
201 }
202 break;
203 }
204 }
205
206
207 //--------- build south wall -----------
208 short southWallFirst;
209 for( southWallFirst = x1; southWallFirst < x2; ++southWallFirst)
210 {
211 if( (locPtr = get_loc(southWallFirst, y2))->can_build_wall() ||
212 ( locPtr->is_wall() && locPtr->wall_town_recno() == townRecno) )
213 {
214 //---------- find place for the south gate ----------//
215 if( y2 <= max_y_loc-GATE_WIDTH+1 && x2-x1 >= GATE_LENGTH)
216 {
217 //----- try from the middle, and then butterfly outward ----//
218 short increment = 0;
219 short trial, southGateX;
220 for( trial=x2-x1-GATE_LENGTH, southGateX=x1+(trial+1)/2;
221 trial > 0; --trial, southGateX += increment)
222 {
223 if(can_build_area(southGateX, y2,
224 southGateX+GATE_LENGTH-1, y2+GATE_WIDTH-1) )
225 {
226 //----------- put south gate -------------//
227 build_south_gate(southGateX, y2, townRecno, initHp);
228 break;
229 }
230 increment = -increment;
231 if( increment >= 0)
232 ++increment;
233 else
234 --increment;
235 }
236 //----------- put other wall -------------//
237 build_south_wall(x1, x2, y2, townRecno, initHp);
238
239 //--------- open north gate ----------//
240 open_south_gate(southGateX, y2, townRecno);
241
242 }
243 else
244 {
245 //---------- y2 too big for gate ----------//
246 if(locPtr->can_build_wall() )
247 {
248 locPtr->set_wall(STOWER, townRecno, initHp);
249 locPtr->set_fire_src(-50);
250 }
251 }
252 break;
253 }
254 }
255
256 }
257 //--------------- end of function World::build_wall_section ----------//
258
259 //--------------- begin of function World::build_west_gate ----------//
build_west_gate(short x1,short y1,short townRecno,short initHp)260 void World::build_west_gate(short x1, short y1, short townRecno, short initHp)
261 {
262 //--------- put two gate towers -----------//
263 Location *locPtr = get_loc(x1,y1);
264 locPtr->set_wall(WGATE_NTOWER_NW, townRecno, initHp);
265 (locPtr+1)->set_wall(WGATE_NTOWER_NE, townRecno, initHp);
266 locPtr->set_fire_src(-50);
267 (locPtr+1)->set_fire_src(-50);
268
269 locPtr = get_loc(x1, y1+1);
270 locPtr->set_wall(WGATE_NTOWER_SW, townRecno, initHp);
271 (locPtr+1)->set_wall(WGATE_NTOWER_SE, townRecno, initHp);
272 locPtr->set_fire_src(-50);
273 (locPtr+1)->set_fire_src(-50);
274
275 locPtr = get_loc(x1,y1+GATE_LENGTH-2);
276 locPtr->set_wall(WGATE_STOWER_NW, townRecno, initHp);
277 (locPtr+1)->set_wall(WGATE_STOWER_NE, townRecno, initHp);
278 locPtr->set_fire_src(-50);
279 (locPtr+1)->set_fire_src(-50);
280
281 locPtr = get_loc(x1, y1+GATE_LENGTH-1);
282 locPtr->set_wall(WGATE_STOWER_SW, townRecno, initHp);
283 (locPtr+1)->set_wall(WGATE_STOWER_SE, townRecno, initHp);
284 locPtr->set_fire_src(-50);
285 (locPtr+1)->set_fire_src(-50);
286
287 //---------- put gate -----------//
288 char gateId = WGATE_BASE;
289 for(short y = 2; y < GATE_LENGTH-2; ++y)
290 {
291 locPtr = get_loc(x1, y1+y);
292 for(short x = 0; x < GATE_WIDTH; ++x, ++locPtr)
293 {
294 locPtr->set_wall(gateId++, townRecno, initHp);
295 locPtr->set_fire_src(-50);
296 }
297 }
298 }
299 //--------------- end of function World::build_west_gate ----------//
300
301 //--------------- begin of function World::build_west_wall ----------//
build_west_wall(short x1,short y1,short y2,short townRecno,short initHp)302 void World::build_west_wall(short x1, short y1, short y2, short townRecno,
303 short initHp)
304 {
305 //---------- find segments of buildable terrain ---------//
306 short startY = y1, endY = y1;
307 while(startY <= y2)
308 {
309 for( ; startY <= y2 && !get_loc(x1,startY)->can_build_wall(); ++startY);
310 if( startY <= y2) // a place is found
311 {
312 //-------- found segment end -----------//
313 for( endY = startY+1; endY <= y2 && get_loc(x1,endY)->can_build_wall() ;++endY);
314 --endY;
315
316 if( startY == endY)
317 {
318 //------- equal square, draw a single tower --------//
319 get_loc(x1, startY)->set_wall(SINGLE_TOWER, townRecno, initHp);
320 get_loc(x1, startY)->set_fire_src(-50);
321 }
322 else
323 {
324 short startSquare = NTOWER;
325 short endSquare = STOWER;
326 // if startY-1 is a wall, hence a gate, start with a wall with shadow
327 if( startY > y1 && get_loc(x1, startY-1)->is_wall() )
328 {
329 startSquare = NSWALL_SHADOW;
330 }
331 // if endY+1 is a wall, hence a gate, start with a wall
332 if( endY < y2 && get_loc(x1, endY+1)->is_wall() )
333 {
334 endSquare = NSWALL;
335 }
336 for( short y = startY; y < endY; ++y)
337 {
338 get_loc(x1, y)->set_wall(startSquare, townRecno, initHp);
339 get_loc(x1, y)->set_fire_src(-50);
340
341 switch(startSquare)
342 {
343 case NTOWER:
344 startSquare = NSWALL_SHADOW;
345 break;
346 case NSWALL_SHADOW:
347 startSquare = NSWALL;
348 break;
349 // otherwise unchange
350 }
351 }
352 get_loc(x1, endY)->set_wall(endSquare, townRecno, initHp);
353 get_loc(x1, endY)->set_fire_src(-50);
354 }
355 startY = endY +1;
356 }
357 }
358 }
359 //--------------- end of function World::build_west_wall ----------//
360
361 //--------------- begin of function World::open_west_gate ----------//
open_west_gate(short x2,short y1,short townRecno)362 void World::open_west_gate(short x2, short y1, short townRecno)
363 {
364 //------ check if any west gate tile is built ---------//
365 Location *locPtr = get_loc(x2,y1+2);
366 if( locPtr->is_wall() && locPtr->wall_id() == WGATE_N &&
367 locPtr->wall_town_recno() == townRecno)
368 {
369 for(short y = 3; y < GATE_LENGTH-3; ++y)
370 for(short x = 0; x < GATE_WIDTH; ++x)
371 get_loc(x2-x, y1+y)->remove_wall();
372
373 }
374 }
375 //--------------- end of function World::open_west_gate ----------//
376
377 //--------------- begin of function World::build_east_gate ----------//
build_east_gate(short x1,short y1,short townRecno,short initHp)378 void World::build_east_gate(short x1, short y1, short townRecno, short initHp)
379 {
380 //---------- put two gate towers ----------//
381 Location *locPtr = get_loc(x1,y1);
382 locPtr->set_wall(EGATE_NTOWER_NW, townRecno, initHp);
383 (locPtr+1)->set_wall(EGATE_NTOWER_NE, townRecno, initHp);
384 locPtr->set_fire_src(-50);
385 (locPtr+1)->set_fire_src(-50);
386
387 locPtr = get_loc(x1, y1+1);
388 locPtr->set_wall(EGATE_NTOWER_SW, townRecno, initHp);
389 (locPtr+1)->set_wall(EGATE_NTOWER_SE, townRecno, initHp);
390 locPtr->set_fire_src(-50);
391 (locPtr+1)->set_fire_src(-50);
392
393 locPtr = get_loc(x1,y1+GATE_LENGTH-2);
394 locPtr->set_wall(EGATE_STOWER_NW, townRecno, initHp);
395 (locPtr+1)->set_wall(EGATE_STOWER_NE, townRecno, initHp);
396 locPtr->set_fire_src(-50);
397 (locPtr+1)->set_fire_src(-50);
398
399 locPtr = get_loc(x1, y1+GATE_LENGTH-1);
400 locPtr->set_wall(EGATE_STOWER_SW, townRecno, initHp);
401 (locPtr+1)->set_wall(EGATE_STOWER_SE, townRecno, initHp);
402 locPtr->set_fire_src(-50);
403 (locPtr+1)->set_fire_src(-50);
404
405 //------------- put gate ----------------//
406 char gateId = EGATE_BASE;
407 for(short y = 2; y < GATE_LENGTH-2; ++y)
408 {
409 locPtr = get_loc(x1, y+y1);
410 for(short x = 0; x < GATE_WIDTH; ++x, ++locPtr)
411 {
412 locPtr->set_wall(gateId++, townRecno, initHp);
413 locPtr->set_fire_src(-50);
414 }
415 }
416 }
417 //--------------- end of function World::build_east_gate ----------//
418
419 //--------------- begin of function World::build_east_wall ----------//
build_east_wall(short x1,short y1,short y2,short townRecno,short initHp)420 void World::build_east_wall(short x1, short y1, short y2, short townRecno,
421 short initHp)
422 {
423 //--------- find segments of buildable terrain ---------//
424 short startY = y1, endY = y1;
425 while(startY <= y2)
426 {
427 for( ; startY <= y2 && !get_loc(x1,startY)->can_build_wall(); ++startY);
428 if( startY <= y2) // a place is found
429 {
430 //-------- found segment end -------------//
431 for( endY = startY+1; endY <= y2 && get_loc(x1,endY)->can_build_wall() ;++endY);
432 --endY;
433
434 if( startY == endY)
435 {
436 //----------- equal square, draw a single tower --------//
437 get_loc(x1, startY)->set_wall(SINGLE_TOWER, townRecno, initHp);
438 get_loc(x1, startY)->set_fire_src(-50);
439 }
440 else
441 {
442 short startSquare = NTOWER;
443 short endSquare = STOWER;
444 // if startY-1 is a wall, hence a gate, start with a wall with shadow
445 if( startY > y1 && get_loc(x1, startY-1)->is_wall() )
446 {
447 startSquare = NSWALL_SHADOW;
448 }
449 // if endY+1 is a wall, hence a gate, start with a wall
450 if( endY < y2 && get_loc(x1, endY+1)->is_wall() )
451 {
452 endSquare = NSWALL;
453 }
454 for( short y = startY; y < endY; ++y)
455 {
456 get_loc(x1, y)->set_wall(startSquare, townRecno, initHp);
457 get_loc(x1, y)->set_fire_src(-50);
458 switch(startSquare)
459 {
460 case NTOWER:
461 startSquare = NSWALL_SHADOW;
462 break;
463 case NSWALL_SHADOW:
464 startSquare = NSWALL;
465 break;
466 // otherwise unchange
467 }
468 }
469 get_loc(x1, endY)->set_wall(endSquare, townRecno, initHp);
470 get_loc(x1, endY)->set_fire_src(-50);
471 }
472 startY = endY +1;
473 }
474 }
475 }
476 //--------------- end of function World::build_east_wall ----------//
477
478 //--------------- begin of function World::open_east_gate ----------//
open_east_gate(short x1,short y1,short townRecno)479 void World::open_east_gate(short x1, short y1, short townRecno)
480 {
481 //------ check if any east gate tile is built ---------//
482 Location *locPtr = get_loc(x1,y1+2);
483 if( locPtr->is_wall() && locPtr->wall_id() == EGATE_N &&
484 locPtr->wall_town_recno() == townRecno)
485 {
486 for(short y = 3; y < GATE_LENGTH-3; ++y)
487 for(short x = 0; x < GATE_WIDTH; ++x)
488 get_loc(x1+x, y1+y)->remove_wall();
489
490 }
491 }
492 //--------------- end of function World::open_east_gate ----------//
493
494 //--------------- begin of function World::build_north_gate ----------//
build_north_gate(short x1,short y1,short townRecno,short initHp)495 void World::build_north_gate(short x1, short y1, short townRecno,
496 short initHp)
497 {
498 //---------- put two gate towers -----------//
499 Location *locPtr = get_loc(x1,y1);
500 locPtr->set_wall(NGATE_WTOWER_NW, townRecno, initHp);
501 (locPtr+1)->set_wall(NGATE_WTOWER_NE, townRecno, initHp);
502 locPtr->set_fire_src(-50);
503 (locPtr+1)->set_fire_src(-50);
504
505 locPtr = get_loc(x1+GATE_LENGTH-2, y1);
506 locPtr->set_wall(NGATE_ETOWER_NW, townRecno, initHp);
507 (locPtr+1)->set_wall(NGATE_ETOWER_NE, townRecno, initHp);
508 locPtr->set_fire_src(-50);
509 (locPtr+1)->set_fire_src(-50);
510
511 locPtr = get_loc(x1,y1+1);
512 locPtr->set_wall(NGATE_WTOWER_SW, townRecno, initHp);
513 (locPtr+1)->set_wall(NGATE_WTOWER_SE, townRecno, initHp);
514 locPtr->set_fire_src(-50);
515 (locPtr+1)->set_fire_src(-50);
516
517 locPtr = get_loc(x1+GATE_LENGTH-2, y1+1);
518 locPtr->set_wall(NGATE_ETOWER_SW, townRecno, initHp);
519 (locPtr+1)->set_wall(NGATE_ETOWER_SE, townRecno, initHp);
520 locPtr->set_fire_src(-50);
521 (locPtr+1)->set_fire_src(-50);
522
523 //------------ put gate -------------//
524 char gateId = NGATE_BASE;
525 for(short y = 0; y < GATE_WIDTH; ++y)
526 {
527 locPtr = get_loc(x1+2, y1+y);
528 for(short x = 2; x < GATE_LENGTH-2; ++x, ++locPtr)
529 {
530 locPtr->set_wall(gateId++, townRecno, initHp);
531 locPtr->set_fire_src(-50);
532 }
533 }
534 }
535 //--------------- end of function World::build_north_gate ----------//
536
537 //--------------- begin of function World::build_north_wall ----------//
build_north_wall(short x1,short x2,short y1,short townRecno,short initHp)538 void World::build_north_wall(short x1, short x2, short y1, short townRecno,
539 short initHp)
540 {
541 //---------- find segments of buildable terrain ---------//
542 short startX = x1, endX = x1;
543 while(startX <= x2)
544 {
545 for( ; startX <= x2 && !get_loc(startX, y1)->can_build_wall(); ++startX);
546 if( startX <= x2) // a place is found
547 {
548 //--------- found segment end ----------//
549 for( endX = startX+1; endX <= x2 && get_loc(endX, y1)->can_build_wall() ;++endX);
550 --endX;
551
552 if( startX == endX)
553 {
554 //---------- equal square, draw a single tower ---------//
555 get_loc(startX, y1)->set_wall(SINGLE_TOWER, townRecno, initHp);
556 get_loc(startX, y1)->set_fire_src(-50);
557 }
558 else
559 {
560 short startSquare = WTOWER;
561 short endSquare = ETOWER;
562 // if startX-1 is a wall, hence a gate, start with a wall with shadow
563 if( startX > x1 && get_loc(startX-1, y1)->is_wall() )
564 {
565 startSquare = EWWALL_SHADOW;
566
567 // if startX-1 is a NTOWER (corner) , change it to NWTOWER
568 Location *leftLoc;
569 if( (leftLoc = get_loc(startX-1, y1))->wall_id() == NTOWER
570 && leftLoc->wall_town_recno() == townRecno )
571 {
572 leftLoc->remove_wall();
573 leftLoc->set_wall(NWTOWER, townRecno, initHp);
574 }
575 }
576 // if endX+1 is a wall, hence a gate, start with a wall
577 if( endX < x2 && get_loc(endX+1, y1)->is_wall() )
578 {
579 endSquare = EWWALL;
580
581 // if endX+1 is a NTOWER (corner) , change it to NETOWER
582 Location *rightLoc;
583 if( (rightLoc = get_loc(endX+1,y1))->wall_id() == NTOWER
584 && rightLoc->wall_town_recno() == townRecno)
585 {
586 rightLoc->remove_wall();
587 rightLoc->set_wall(NETOWER, townRecno, initHp);
588 }
589 }
590 for( short x = startX; x < endX; ++x)
591 {
592 get_loc(x, y1)->set_wall(startSquare, townRecno, initHp);
593 get_loc(x, y1)->set_fire_src(-50);
594 switch(startSquare)
595 {
596 case WTOWER:
597 startSquare = EWWALL_SHADOW;
598 break;
599 case EWWALL_SHADOW:
600 startSquare = EWWALL;
601 break;
602 // otherwise unchange
603 }
604 }
605 get_loc(endX, y1)->set_wall(endSquare, townRecno, initHp);
606 get_loc(endX, y1)->set_fire_src(-50);
607 }
608 startX = endX +1;
609 }
610 }
611 }
612 //--------------- end of function World::build_north_wall ----------//
613
614 //--------------- begin of function World::open_north_gate ----------//
open_north_gate(short x1,short y2,short townRecno)615 void World::open_north_gate(short x1, short y2, short townRecno)
616 {
617 //------ check if any north gate tile is built ---------//
618 Location *locPtr = get_loc(x1+2,y2);
619 if( locPtr->is_wall() && locPtr->wall_id() == NGATE_W &&
620 locPtr->wall_town_recno() == townRecno)
621 {
622 for(short x = 3; x < GATE_LENGTH-3; ++x)
623 for(short y = 0; y < GATE_WIDTH; ++y)
624 get_loc(x1+x, y2-y)->remove_wall();
625
626 }
627 }
628 //--------------- end of function World::open_north_gate ----------//
629
630 //--------------- begin of function World::build_south_gate ----------//
build_south_gate(short x1,short y1,short townRecno,short initHp)631 void World::build_south_gate(short x1, short y1, short townRecno, short initHp)
632 {
633 //---------- put two gate towers ----------//
634 Location *locPtr = get_loc(x1,y1);
635 locPtr->set_wall(SGATE_WTOWER_NW, townRecno, initHp);
636 (locPtr+1)->set_wall(SGATE_WTOWER_NE, townRecno, initHp);
637 locPtr->set_fire_src(-50);
638 (locPtr+1)->set_fire_src(-50);
639
640 locPtr = get_loc(x1+GATE_LENGTH-2, y1);
641 locPtr->set_wall(SGATE_ETOWER_NW, townRecno, initHp);
642 (locPtr+1)->set_wall(SGATE_ETOWER_NE, townRecno, initHp);
643 locPtr->set_fire_src(-50);
644 (locPtr+1)->set_fire_src(-50);
645
646 locPtr = get_loc(x1,y1+1);
647 locPtr->set_wall(SGATE_WTOWER_SW, townRecno, initHp);
648 (locPtr+1)->set_wall(SGATE_WTOWER_SE, townRecno, initHp);
649 locPtr->set_fire_src(-50);
650 (locPtr+1)->set_fire_src(-50);
651
652 locPtr = get_loc(x1+GATE_LENGTH-2, y1+1);
653 locPtr->set_wall(SGATE_ETOWER_SW, townRecno, initHp);
654 (locPtr+1)->set_wall(SGATE_ETOWER_SE, townRecno, initHp);
655 locPtr->set_fire_src(-50);
656 (locPtr+1)->set_fire_src(-50);
657
658 //------------ put gate --------------//
659 char gateId = SGATE_BASE;
660 for(short y = 0; y < GATE_WIDTH; ++y)
661 {
662 locPtr = get_loc(x1+2, y1+y);
663 for(short x = 2; x < GATE_LENGTH-2; ++x, ++locPtr)
664 {
665 locPtr->set_wall(gateId++, townRecno, initHp);
666 locPtr->set_fire_src(-50);
667 }
668 }
669 }
670 //--------------- end of function World::build_south_gate ----------//
671
672 //--------------- begin of function World::build_south_wall ----------//
build_south_wall(short x1,short x2,short y1,short townRecno,short initHp)673 void World::build_south_wall(short x1, short x2, short y1, short townRecno,
674 short initHp)
675 {
676 //----------- find segments of buildable terrain -------------//
677 short startX = x1, endX = x1;
678 while(startX <= x2)
679 {
680 for( ; startX <= x2 && !get_loc(startX, y1)->can_build_wall(); ++startX);
681 if( startX <= x2) // a place is found
682 {
683 //---------- found segment end ---------//
684 for( endX = startX+1; endX <= x2 && get_loc(endX, y1)->can_build_wall() ;++endX);
685 --endX;
686
687 if( startX == endX)
688 {
689 //--------- equal square, draw a single tower --------//
690 get_loc(startX, y1)->set_wall(SINGLE_TOWER, townRecno, initHp);
691 get_loc(startX, y1)->set_fire_src(-50);
692 }
693 else
694 {
695 short startSquare = WTOWER;
696 short endSquare = ETOWER;
697 // if startX-1 is a wall, hence a gate, start with a wall with shadow
698 if( startX > x1 && get_loc(startX-1, y1)->is_wall() )
699 {
700 startSquare = EWWALL_SHADOW;
701 // if startX-1 is a STOWER (corner) , change it to SWTOWER
702 Location *leftLoc;
703 if( (leftLoc = get_loc(startX-1, y1))->wall_id() == STOWER
704 && leftLoc->wall_town_recno() == townRecno )
705 {
706 leftLoc->remove_wall();
707 leftLoc->set_wall(SWTOWER, townRecno, initHp);
708 }
709 }
710 // if endY+1 is a wall, hence a gate, start with a wall with shadow
711 if( endX < x2 && get_loc(endX+1, y1)->is_wall() )
712 {
713 endSquare = EWWALL;
714
715 // if endX+1 is a STOWER (corner) , change it to SETOWER
716 Location *rightLoc;
717 if( (rightLoc = get_loc(endX+1, y1))->wall_id() == STOWER
718 && rightLoc->wall_town_recno() == townRecno)
719 {
720 rightLoc->remove_wall();
721 rightLoc->set_wall(SETOWER, townRecno, initHp);
722 }
723
724 }
725 for( short x = startX; x < endX; ++x)
726 {
727 get_loc(x, y1)->set_wall(startSquare, townRecno, initHp);
728 get_loc(x, y1)->set_fire_src(-50);
729 switch(startSquare)
730 {
731 case WTOWER:
732 startSquare = EWWALL_SHADOW;
733 break;
734 case EWWALL_SHADOW:
735 startSquare = EWWALL;
736 break;
737 // otherwise unchange
738 }
739 }
740 get_loc(endX, y1)->set_wall(endSquare, townRecno, initHp);
741 get_loc(endX, y1)->set_fire_src(-50);
742 }
743 startX = endX +1;
744 }
745 }
746 }
747 //--------------- end of function World::build_south_wall ----------//
748
749 //--------------- begin of function World::open_south_gate ----------//
open_south_gate(short x1,short y1,short townRecno)750 void World::open_south_gate(short x1, short y1, short townRecno)
751 {
752 //------ check if any south gate tile is built ---------//
753 Location *locPtr = get_loc(x1+2,y1);
754 if( locPtr->is_wall() && locPtr->wall_id() == SGATE_W &&
755 locPtr->wall_town_recno() == townRecno)
756 {
757 for(short x = 3; x < GATE_LENGTH-3; ++x)
758 for(short y = 0; y < GATE_WIDTH; ++y)
759 get_loc(x1+x, y1+y)->remove_wall();
760
761 }
762 }
763 //--------------- end of function World::open_south_gate ----------//
764
765 //--------------- begin of function World::form_wall -----------//
766 //
767 // adjust wall tile, return no. of tile changed
768 //
form_wall(short x,short y,short maxRecur)769 int World::form_wall(short x, short y, short maxRecur)
770 {
771 Location *locPtr = get_loc(x,y);
772 if( !locPtr->is_wall() || maxRecur < 0)
773 return 0;
774
775 int wallTile = locPtr->wall_id();
776 int blockChanged = 0;
777
778 int flag = 0;
779 if( y == 0 || get_loc(x,y-1)->is_wall()) // north square
780 flag |= 1;
781 if( x == max_x_loc-1 || get_loc(x+1,y)->is_wall() ) // east square
782 flag |= 2;
783 if( y == max_y_loc-1 || get_loc(x,y+1)->is_wall() ) // south square
784 flag |= 4;
785 if( x == 0 || get_loc(x-1,y)->is_wall() ) // west square
786 flag |= 8;
787 int newWallTile, newWallRubble;
788
789 // ------- find new wall tile ---------//
790 switch(flag)
791 {
792 case 0: // no surrounding square is wall
793 newWallTile = SINGLE_TOWER;
794 newWallRubble = TOWER_CON1;
795 break;
796 case 1: // only north square is wall
797 newWallTile = STOWER;
798 newWallRubble = TOWER_CON1;
799 break;
800 case 2: // only east
801 newWallTile = WTOWER;
802 newWallRubble = TOWER_CON1;
803 break;
804 case 3: // north and east
805 newWallTile = SWTOWER;
806 newWallRubble = TOWER_CON1;
807 break;
808 case 4: // south only
809 newWallTile = NTOWER;
810 newWallRubble = TOWER_CON1;
811 break;
812 case 5: // north and south
813 newWallTile = NSWALL;
814 if( y > 0 && get_loc(x,y-1)->is_wall() )
815 {
816 int northWallTile = get_loc(x,y-1)->wall_id();
817 if( northWallTile != NSWALL && northWallTile != NSWALL_SHADOW &&
818 !is_wall_rubble(northWallTile))
819 newWallTile = NSWALL_SHADOW;
820 }
821 newWallRubble = NSWALL_CON1;
822 break;
823 case 6: // east and south
824 newWallTile = NWTOWER;
825 newWallRubble = TOWER_CON1;
826 break;
827 case 7: // east and north and south
828 newWallTile = NWTOWER;
829 newWallRubble = TOWER_CON1;
830 break;
831 case 8: // west only
832 newWallTile = ETOWER;
833 newWallRubble = TOWER_CON1;
834 break;
835 case 9: // west and north
836 newWallTile = SETOWER;
837 newWallRubble = TOWER_CON1;
838 break;
839 case 10: // west and east
840 newWallTile = EWWALL;
841 if( x > 0 && get_loc(x-1,y)->is_wall() )
842 {
843 int westWallTile = get_loc(x-1,y)->wall_id();
844 if( westWallTile != EWWALL && westWallTile != EWWALL_SHADOW &&
845 !is_wall_rubble(westWallTile) )
846 newWallTile = EWWALL_SHADOW;
847 }
848 newWallRubble = EWWALL_CON1;
849 break;
850 case 11: // west and east and north
851 newWallTile = ETOWER;
852 newWallRubble = TOWER_CON1;
853 break;
854 case 12: // west and south
855 newWallTile = NETOWER;
856 newWallRubble = TOWER_CON1;
857 break;
858 case 13: // west and south and north
859 newWallTile = NETOWER;
860 newWallRubble = TOWER_CON1;
861 break;
862 case 14: // west and south and east
863 newWallTile = NETOWER;
864 newWallRubble = TOWER_CON1;
865 break;
866 case 15: // all four
867 newWallTile = NETOWER;
868 newWallRubble = TOWER_CON1;
869 break;
870 }
871
872 // --- adjust newWallTile from wall_grade() ------//
873 switch(get_loc(x,y)->wall_grade())
874 {
875 case 1:
876 newWallTile = newWallRubble;
877 break;
878 case -1:
879 newWallTile = newWallRubble + TOWER_DES1 - TOWER_CON1; // e.g. TOWER_CON1 -> TOWER_DES1
880 break;
881 case 2:
882 newWallTile = newWallRubble + 1;
883 break;
884 case -2:
885 newWallTile = newWallRubble + TOWER_DES2 - TOWER_CON1;
886 break;
887 case 3:
888 newWallTile = newWallRubble + 2;
889 break;
890 case -3:
891 newWallTile = newWallRubble + TOWER_DES3 - TOWER_CON1;
892 break;
893 case 4:
894 case -4:
895 // no change
896 break;
897 default:
898 err_here();
899 }
900
901 // --- change wall tile, such as change to tower, add shadow ----//
902 if( wallTile != newWallTile)
903 {
904 locPtr->chg_wall_id(newWallTile);
905 blockChanged ++;
906 }
907
908 // change adjacent sqaure
909 if( y > 0 && get_loc(x,y-1)->is_wall() )
910 blockChanged += form_wall(x, y-1, maxRecur-1);
911 if( y < max_y_loc-1 && get_loc(x,y+1)->is_wall() )
912 blockChanged += form_wall(x, y+1, maxRecur-1);
913 if( x < max_x_loc-1 && get_loc(x+1,y)->is_wall() )
914 blockChanged += form_wall(x+1, y, maxRecur-1);
915 if( x > 0 && get_loc(x-1,y)->is_wall() )
916 blockChanged += form_wall(x-1, y, maxRecur-1);
917
918 return blockChanged;
919 }
920 //--------------- end of function World::form_wall -----------//
921
922
923 //--------------- begin of function World::correct_wall -----------//
924 //
925 // adjust adjacent wall tiles, return no. of tile changed
926 //
correct_wall(short x,short y,short maxRecur)927 int World::correct_wall(short x, short y, short maxRecur)
928 {
929 if( maxRecur < 0)
930 return 0;
931
932 int blockChanged = 0;
933 // change adjacent sqaure
934 if( y > 0 && get_loc(x,y-1)->is_wall() )
935 blockChanged += form_wall(x, y-1, maxRecur-1);
936 if( y < max_y_loc-1 && get_loc(x,y+1)->is_wall() )
937 blockChanged += form_wall(x, y+1, maxRecur-1);
938 if( x < max_x_loc-1 && get_loc(x+1,y)->is_wall() )
939 blockChanged += form_wall(x+1, y, maxRecur-1);
940 if( x > 0 && get_loc(x-1,y)->is_wall() )
941 blockChanged += form_wall(x-1, y, maxRecur-1);
942
943 return blockChanged;
944 }
945
946
947 //---------- begin of function World::form_world_wall -----//
form_world_wall()948 void World::form_world_wall()
949 {
950 static int init_build_wall_seq = 0;
951 #define SPACING 12
952 static char build_wall_x_seq[SPACING*SPACING];
953 static char build_wall_y_seq[SPACING*SPACING];
954 static int next_build_wall_seq;
955
956 int x, y;
957
958 if(! init_build_wall_seq )
959 {
960 init_build_wall_seq = 1;
961 long seed = misc.get_random_seed();
962 // ------ initialize with linear sequence----- //
963 for( y = 0; y < SPACING; ++y)
964 {
965 for( x = 0; x < SPACING; ++x)
966 {
967 build_wall_x_seq[y*SPACING+x] = x;
968 build_wall_y_seq[y*SPACING+x] = y;
969 }
970 }
971
972 misc.set_random_seed(176682233); // hard code
973
974 //------- shuffle randomly ----------//
975 for(int t = SPACING * SPACING -1; t >= 0; --t)
976 {
977 int u = misc.random(SPACING * SPACING);
978
979 // ----- swap build_wall_x/y_seq[t] with [u]
980 char tmp;
981 tmp = build_wall_x_seq[t];
982 build_wall_x_seq[t] = build_wall_x_seq[u];
983 build_wall_x_seq[u] = tmp;
984 tmp = build_wall_y_seq[t];
985 build_wall_y_seq[t] = build_wall_y_seq[u];
986 build_wall_y_seq[u] = tmp;
987 }
988 next_build_wall_seq = 0;
989 misc.set_random_seed(seed);
990 }
991
992 for(int trial = 7; trial > 0 ; --trial)
993 {
994 for(y = build_wall_y_seq[next_build_wall_seq]; y < max_y_loc; y+= SPACING)
995 {
996 for(x = build_wall_x_seq[next_build_wall_seq]; x < max_x_loc; x+= SPACING)
997 {
998 Location *locPtr = get_loc(x,y);
999 // ######## begin Gilbert 7/3 ##########//
1000 if( locPtr->had_wall() )
1001 {
1002 locPtr->dec_wall_timeout();
1003 }
1004 else if( locPtr->is_wall())
1005 // ######## end Gilbert 7/3 ##########//
1006 {
1007 int prevGrade = locPtr->wall_grade();
1008 int newGrade;
1009 if( locPtr->inc_wall_hit_point(WALL_GROWTH_RATE) == 0)
1010 {
1011 locPtr->remove_wall();
1012 if( y > 0 && get_loc(x,y-1)->is_wall() )
1013 form_wall(x,y-1, 1);
1014 if( y < max_y_loc-1 && get_loc(x,y+1)->is_wall() )
1015 form_wall(x,y+1, 1);
1016 if( x > 0 && get_loc(x-1,y)->is_wall() )
1017 form_wall(x-1,y, 1);
1018 if( x < max_x_loc-1 && get_loc(x+1,y)->is_wall() )
1019 form_wall(x+1,y, 1);
1020 }
1021 else if( prevGrade != (newGrade=locPtr->wall_grade()) )
1022 {
1023 form_wall(x,y,2);
1024 }
1025 }
1026 }
1027 }
1028 next_build_wall_seq = (next_build_wall_seq+1) % (SPACING*SPACING);
1029 }
1030 }
1031 //---------- end of function World::form_world_wall -----//
1032
1033
1034 //------- Begin of function World::build_wall_tile -------//
1035 //
1036 // <int> xLoc, yLoc - the location on which the wall should be built
1037 // <int> nationRecno - recno of the builder nation
1038 //
1039 // see also ZoomMatrix->draw_build_marker
1040 //
build_wall_tile(int xLoc,int yLoc,short nationRecno,char remoteAction)1041 void World::build_wall_tile(int xLoc, int yLoc, short nationRecno, char remoteAction)
1042 {
1043 Location *locPtr = get_loc(xLoc, yLoc);
1044 if( can_build_wall(xLoc, yLoc, nationRecno))
1045 {
1046 if( !remoteAction && remote.is_enable() )
1047 {
1048 // packet structure : <nation recno> <xLoc> <yLoc>
1049 short *shortPtr = (short *)remote.new_send_queue_msg(MSG_WALL_BUILD, 3*sizeof(short));
1050 shortPtr[0] = nationRecno;
1051 shortPtr[1] = xLoc;
1052 shortPtr[2] = yLoc;
1053 }
1054 else
1055 {
1056 locPtr->set_wall(TOWER_CON1,nationRecno, 1);
1057 locPtr->set_fire_src(-50);
1058 // nation_array[nationRecno]->add_expense( (float)BUILD_WALL_COST );
1059 }
1060 }
1061 else if( locPtr->is_wall_destructing() &&
1062 can_destruct_wall(xLoc, yLoc, nationRecno))
1063 {
1064 if( !remoteAction && remote.is_enable() )
1065 {
1066 // packet structure : <nation recno> <xLoc> <yLoc>
1067 short *shortPtr = (short *)remote.new_send_queue_msg(MSG_WALL_BUILD, 3*sizeof(short));
1068 shortPtr[0] = nationRecno;
1069 shortPtr[1] = xLoc;
1070 shortPtr[2] = yLoc;
1071 }
1072 else
1073 {
1074 locPtr->set_wall_creating();
1075 // nation_array[nationRecno]->add_expense( (float)
1076 // BUILD_WALL_COST * (100-locPtr->wall_abs_hit_point()) / 100 );
1077 }
1078 }
1079
1080 }
1081 //--------- End of function World::build_wall_tile ---------//
1082
1083
1084 //------- Begin of function World::destruct_wall_tile -------//
1085 //
1086 // <int> xLoc, yLoc - the location on which the wall should be destructed
1087 // <int> nationRecno - recno of the destructer nation
1088 //
1089 // see also ZoomMatrix->draw_build_marker
1090 //
destruct_wall_tile(int xLoc,int yLoc,short nationRecno,char remoteAction)1091 void World::destruct_wall_tile(int xLoc, int yLoc, short nationRecno, char remoteAction)
1092 {
1093 Location *locPtr = get_loc(xLoc, yLoc);
1094
1095 if( locPtr->is_wall_creating() && can_destruct_wall(xLoc, yLoc, nationRecno) )
1096 {
1097 if( !remoteAction && remote.is_enable() )
1098 {
1099 // packet structure : <nation recno> <xLoc> <yLoc>
1100 short *shortPtr = (short *)remote.new_send_queue_msg(MSG_WALL_DESTRUCT, 3*sizeof(short));
1101 shortPtr[0] = nationRecno;
1102 shortPtr[1] = xLoc;
1103 shortPtr[2] = yLoc;
1104 }
1105 else
1106 {
1107 locPtr->set_wall_destructing();
1108 // nation_array[nationRecno]->add_expense( (float) DESTRUCT_WALL_COST );
1109 }
1110 }
1111 }
1112 //--------- End of function World::destruct_wall_tile ---------//
1113