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 : OWORLD.CPP
22 //Description : Object World
23
24 #include <OSYS.h>
25 #include <OGAME.h>
26 #include <OVGA.h>
27 #include <OFONT.h>
28 #include <OMOUSE.h>
29 #include <OMOUSECR.h>
30 #include <OFIRMRES.h>
31 #include <OPLANT.h>
32 #include <OPOWER.h>
33 #include <OSITE.h>
34 #include <OINFO.h>
35 #include <OTOWN.h>
36 #include <ONATION.h>
37 #include <OWEATHER.h>
38 #include <OTERRAIN.h>
39 #include <OWORLD.h>
40 #include <OANLINE.h>
41 #include <OTORNADO.h>
42 #include <OU_VEHI.h>
43 #include <OSERES.h>
44 #include <OREMOTE.h>
45 #include <ONEWS.h>
46
47
48 //------------ Define static class variables ------------//
49
50 short World::view_top_x, World::view_top_y;
51 int World::max_x_loc=200, World::max_y_loc=200;
52
53 //----------- Begin of function World::World ----------//
54
World()55 World::World()
56 {
57 loc_matrix = NULL;
58 next_scroll_time = 0;
59 scan_fire_x = 0;
60 scan_fire_y = 0;
61 lightning_signal = 0;
62 plant_count = 0;
63 plant_limit = 0;
64
65 //------- initialize matrix objects -------//
66
67 map_matrix = new MapMatrix;
68 zoom_matrix = new ZoomMatrix;
69 }
70 //------------- End of function World::World -----------//
71
72
73 //----------- Begin of function World::~World ----------//
74
~World()75 World::~World()
76 {
77 if( map_matrix )
78 {
79 delete map_matrix;
80 map_matrix = NULL;
81 }
82
83 if( zoom_matrix )
84 {
85 delete zoom_matrix;
86 zoom_matrix = NULL;
87 }
88
89 deinit();
90 }
91 //------------- End of function World::~World -----------//
92
93
94 //----------- Begin of function World::init ----------//
95
init()96 void World::init()
97 {
98 //----------- initialize vars -------------//
99
100 scan_fire_x = 0;
101 scan_fire_y = 0;
102 lightning_signal = 0;
103
104 map_matrix->init_para();
105 zoom_matrix->init_para();
106 }
107 //------------- End of function World::init -----------//
108
109
110 //----------- Begin of function World::deinit ----------//
111
deinit()112 void World::deinit()
113 {
114 if( loc_matrix )
115 {
116 mem_del( loc_matrix );
117 loc_matrix = NULL;
118 }
119 }
120 //------------- End of function World::deinit -----------//
121
122
123 //--------- Begin of function World::assign_map ----------//
124 //
125 // After a map is loaded, assign_map() need to be called to
126 // initial map_matrix and zoom_matrix
127 //
assign_map()128 void World::assign_map()
129 {
130 //------------- assign map -------------//
131
132 map_matrix-> assign_map(loc_matrix, max_x_loc, max_y_loc );
133 zoom_matrix->assign_map(loc_matrix, max_x_loc, max_y_loc );
134
135 //-------- set the zoom area box on map matrix ------//
136
137 map_matrix->cur_x_loc = 0;
138 map_matrix->cur_y_loc = 0;
139 map_matrix->cur_cargo_width = zoom_matrix->disp_x_loc;
140 map_matrix->cur_cargo_height = zoom_matrix->disp_y_loc;
141 }
142 //----------- End of function World::assign_map ----------//
143
144
145 //----------- Begin of function World::paint ------------//
146 //
147 // Paint world window and scroll bars
148 //
paint()149 void World::paint()
150 {
151 map_matrix->paint();
152 zoom_matrix->paint();
153 }
154 //----------- End of function World::paint ------------//
155
156
157 //----------- Begin of function World::refresh ------------//
158 //
refresh()159 void World::refresh()
160 {
161 map_matrix->refresh();
162 zoom_matrix->refresh();
163 }
164 //----------- End of function World::refresh ------------//
165
166
167 //----------- Begin of function World::process ------------//
168 //
169 // Called every frame
170 //
process()171 void World::process()
172 {
173 //-------- process wall ----------//
174
175 form_world_wall();
176
177 //-------- process fire -----------//
178
179 // BUGHERE : set Location::flammability for every change in cargo
180
181 world.spread_fire(weather);
182
183 // ------- process visibility --------//
184 process_visibility();
185
186 //-------- process lightning ------//
187 // ###### begin Gilbert 11/8 ########//
188 if(lightning_signal== 0 && weather.is_lightning())
189 {
190 // ------- create new lightning ----------//
191 lightning_signal = 110;
192 }
193 if( lightning_signal == 106 && config.weather_effect)
194 {
195 lightning_strike(misc.random(MAX_MAP_WIDTH), misc.random(MAX_MAP_HEIGHT), 1);
196 }
197 if(lightning_signal == 100)
198 lightning_signal = 5 + misc.random(10);
199 else if( lightning_signal)
200 lightning_signal--;
201 // ###### end Gilbert 11/8 ########//
202
203 //---------- process ambient sound ---------//
204
205 if( sys.frame_count%10 == 0 ) // process once per ten frames
206 process_ambient_sound();
207
208 // --------- update scan fire x y ----------//
209 if(++scan_fire_x >= SCAN_FIRE_DIST)
210 {
211 scan_fire_x = 0;
212 if( ++scan_fire_y >= SCAN_FIRE_DIST)
213 scan_fire_y =0;
214 }
215
216 }
217 //----------- End of function World::process ------------//
218
219
220 //----------- Begin of function World::next_day ------------//
221 //
222 // Called every frame
223 //
next_day()224 void World::next_day()
225 {
226 plant_ops();
227
228 weather = weather_forecast[0];
229
230 for(int foreDay=0; foreDay < MAX_WEATHER_FORECAST-1; ++foreDay)
231 {
232 weather_forecast[foreDay] = weather_forecast[foreDay+1];
233 }
234
235 weather_forecast[MAX_WEATHER_FORECAST-1].next_day();
236
237 // ####### begin Gilbert 11/7 #########//
238 magic_weather.next_day();
239 // ####### end Gilbert 11/7 #########//
240
241 if(weather.has_tornado() && config.weather_effect)
242 {
243 tornado_array.add_tornado(weather.tornado_x_loc(max_x_loc, max_y_loc),
244 weather.tornado_y_loc(max_x_loc, max_y_loc), 600);
245 }
246
247 // ######## begin Gilbert 31/7 #######//
248 if( weather.is_quake() && config.random_event_frequency)
249 // ######## end Gilbert 31/7 #######//
250 {
251 earth_quake();
252 }
253
254 //-------- Debug code: BUGHERE ----------//
255
256 #ifdef DEBUG
257
258 Location* locPtr = loc_matrix;
259
260 for( int y=0 ; y<MAX_WORLD_Y_LOC ; y++ )
261 {
262 for( int x=0 ; x<MAX_WORLD_X_LOC ; x++ )
263 {
264 if( locPtr->has_unit(UNIT_LAND) )
265 {
266 err_when( unit_array.is_truly_deleted( locPtr->unit_recno(UNIT_LAND) ) );
267 }
268
269 locPtr++;
270 }
271 }
272
273 #endif
274 }
275 //----------- End of function World::next_day ------------//
276
277
278 //----------- Begin of function World::detect ------------//
279 //
280 // Detect mouse action from user
281 //
282 // Return : 1 - mouse pressed on World area
283 // 0 - mouse not pressed on World area
284 //
detect()285 int World::detect()
286 {
287 if( map_matrix->detect() )
288 return 1;
289
290 if( zoom_matrix->detect() )
291 return 1;
292
293 if( detect_scroll() )
294 return 1;
295
296 // ##### begin Gilbert 16/9 #######//
297 // return detect_firm_town();
298 return 0;
299 // ##### end Gilbert 16/9 #######//
300 }
301 //----------- End of function World::detect ------------//
302
303
304 //--------- Begin of function World::detect_scroll ---------//
305 //
306 // Detect if the mouse cursor is pushed towards the border
307 // of the screen to scroll the zoom window.
308 //
detect_scroll()309 int World::detect_scroll()
310 {
311 int scroll_x = 0, scroll_y = 0;
312 if( !vga.is_input_grabbed() && !mouse.get_scroll(&scroll_x, &scroll_y))
313 return 0;
314
315 if( mouse_cursor.frame_flag ) // if it's now in frame selection mode
316 return 0;
317
318 if( next_scroll_time && misc.get_time() < next_scroll_time ) // just scrolled not too long ago, wait for a little while before next scroll.
319 return 0;
320
321 int rc=0;
322
323 if ( scroll_x || scroll_y )
324 {
325 zoom_matrix->scroll(scroll_x, scroll_y);
326 rc = 1;
327 }
328 else
329 {
330 //----- scroll left -----//
331
332 if (mouse.cur_x <= mouse.bound_x1) {
333 zoom_matrix->scroll(-1, 0);
334 rc = 1;
335 }
336
337 //---- scroll right -----//
338
339 if (mouse.cur_x >= mouse.bound_x2) {
340 zoom_matrix->scroll(1, 0);
341 rc = 1;
342 }
343
344 //---- scroll top -------//
345
346 if (mouse.cur_y <= mouse.bound_y1) {
347 zoom_matrix->scroll(0, -1);
348 rc = 1;
349 }
350
351 //---- scroll bottom ----//
352
353 if (mouse.cur_y >= mouse.bound_y2) {
354 zoom_matrix->scroll(0, 1);
355 rc = 1;
356 }
357
358 //----- set next scroll time based on scroll_speed -----//
359 //
360 // slowest scroll speed: 500/1 = 500 milliseconds or 1/2 second
361 // fastest scroll speed: 500/10 = 50 milliseconds or 1/20 second
362 //
363 //------------------------------------------------------//
364 }
365
366 if( rc )
367 {
368 sys.zoom_need_redraw = 1; // ask the zoom window to refresh next time
369 next_scroll_time = misc.get_time() + 500/(config.scroll_speed+1);
370 }
371
372 return rc;
373 }
374 //----------- End of function World::detect_scroll -----------//
375
376
377 //--------- Begin of function World::go_loc --------//
378 //
379 // Go to a specified location.
380 //
381 // <int> xLoc, yLoc - location to go to.
382 // [int] selectFlag - whether should the object on the location if
383 // there is one. (default: 0)
384 //
go_loc(int xLoc,int yLoc,int selectFlag)385 void World::go_loc(int xLoc, int yLoc, int selectFlag)
386 {
387 //------- set location ---------//
388
389 zoom_matrix->cur_x_loc = xLoc;
390 zoom_matrix->cur_y_loc = yLoc;
391
392 map_matrix->cur_x_loc = xLoc - zoom_matrix->disp_x_loc/2;
393 map_matrix->cur_y_loc = yLoc - zoom_matrix->disp_y_loc/2;
394
395 //--------- refresh ------------//
396
397 map_matrix->valid_cur_box();
398
399 zoom_matrix->top_x_loc = map_matrix->cur_x_loc;
400 zoom_matrix->top_y_loc = map_matrix->cur_y_loc;
401
402 sys.zoom_need_redraw = 1;
403
404 //---- if should select the object on the location ----//
405
406 if( selectFlag )
407 {
408 Location* locPtr = world.get_loc(xLoc, yLoc);
409
410 if( locPtr->has_any_unit() )
411 {
412 int mobileType;
413 int unitRecno = locPtr->get_any_unit( mobileType );
414
415 power.reset_selection();
416
417 unit_array[unitRecno]->selected_flag = 1;
418 unit_array.selected_recno = unitRecno;
419 unit_array.selected_count++;
420 }
421 else if( locPtr->is_firm() )
422 {
423 int firmRecno = locPtr->firm_recno();
424
425 power.reset_selection();
426
427 firm_array.selected_recno = firmRecno;
428 firm_array[firmRecno]->sort_worker();
429 }
430 else if( locPtr->is_town() )
431 {
432 power.reset_selection();
433 town_array.selected_recno = locPtr->town_recno();
434 }
435 else if( locPtr->has_site() )
436 {
437 power.reset_selection();
438 site_array.selected_recno = locPtr->site_recno();
439 }
440 }
441
442 //------- refresh the display -------//
443
444 info.disp();
445 }
446 //----------- End of function World::go_loc --------//
447
448
449 //-------- Begin of function World::unveil ---------//
450 //
451 // Unveil all surrounding areas of the given object.
452 //
453 // <int> xLoc1, yLoc1 = the position of the object.
454 // <int> xLoc2, yLoc2 = the position of the object.
455 //
unveil(int xLoc1,int yLoc1,int xLoc2,int yLoc2)456 void World::unveil(int xLoc1, int yLoc1, int xLoc2, int yLoc2)
457 {
458 if( config.explore_whole_map )
459 return;
460
461 xLoc1 = MAX( 0, xLoc1 - EXPLORE_RANGE);
462 yLoc1 = MAX( 0, yLoc1 - EXPLORE_RANGE);
463 xLoc2 = MIN( MAX_WORLD_X_LOC-1, xLoc2 + EXPLORE_RANGE);
464 yLoc2 = MIN( MAX_WORLD_Y_LOC-1, yLoc2 + EXPLORE_RANGE);
465
466 explore( xLoc1, yLoc1, xLoc2, yLoc2 );
467 }
468 //--------- End of function World::unveil ---------//
469
470
471 //-------- Begin of function World::explore ---------//
472 //
473 // Explore a specific area. No further exploration around the area.
474 //
475 // <int> xLoc1, yLoc1 = the position of the area.
476 // <int> xLoc2, yLoc2 = the position of the area.
477 //
explore(int xLoc1,int yLoc1,int xLoc2,int yLoc2)478 void World::explore(int xLoc1, int yLoc1, int xLoc2, int yLoc2)
479 {
480 if( config.explore_whole_map )
481 return;
482
483 int xLoc, yLoc;
484 Location* locPtr;
485 char* imageBuf = map_matrix->save_image_buf + sizeof(short)*2;
486 char* nationColorArray = nation_array.nation_power_color_array;
487 char* writePtr;
488
489 int shadowMapDist = max_x_loc + 1;
490 int tileYOffset;
491 Location *northWestPtr;
492 char tilePixel;
493
494 for( yLoc=yLoc1 ; yLoc<=yLoc2 ; yLoc++ )
495 {
496 locPtr = get_loc(xLoc1, yLoc);
497
498 for( xLoc=xLoc1 ; xLoc<=xLoc2 ; xLoc++, locPtr++ )
499 {
500 if( !locPtr->explored() )
501 {
502 locPtr->explored_on();
503
504 //-------- draw pixel ----------//
505
506 writePtr = imageBuf+MAP_WIDTH*yLoc+xLoc;
507
508 switch( world.map_matrix->map_mode )
509 {
510 case MAP_MODE_TERRAIN:
511 if( locPtr->fire_str() > 0)
512 *writePtr = (char) FIRE_COLOR;
513
514 else if( locPtr->is_plant() )
515 *writePtr = plant_res.plant_map_color;
516
517 else
518 {
519 tileYOffset = (yLoc & TERRAIN_TILE_Y_MASK) * TERRAIN_TILE_WIDTH;
520
521 tilePixel = terrain_res.get_map_tile(locPtr->terrain_id)[tileYOffset + (xLoc & TERRAIN_TILE_X_MASK)];
522
523 if( xLoc == 0 || yLoc == 0)
524 {
525 *writePtr = tilePixel;
526 }
527 else
528 {
529 northWestPtr = locPtr - shadowMapDist;
530 if( (terrain_res[locPtr->terrain_id]->average_type >=
531 terrain_res[northWestPtr->terrain_id]->average_type) )
532 {
533 *writePtr = tilePixel;
534 }
535 else
536 {
537 *writePtr = (char) VGA_GRAY;
538 }
539 }
540 break;
541 }
542 break;
543
544 case MAP_MODE_SPOT:
545 if( locPtr->sailable() )
546 *writePtr = (char) 0x32;
547
548 else if( locPtr->has_hill() )
549 *writePtr = (char) V_BROWN;
550
551 else if( locPtr->is_plant() )
552 *writePtr = (char) V_DARK_GREEN;
553
554 else
555 *writePtr = (char) VGA_GRAY+10;
556 break;
557
558 case MAP_MODE_POWER:
559 if( locPtr->sailable() )
560 *writePtr = (char) 0x32;
561
562 else if( locPtr->has_hill() )
563 *writePtr = (char) V_BROWN;
564
565 else if( locPtr->is_plant() )
566 *writePtr = (char) V_DARK_GREEN;
567
568 else
569 *writePtr = nationColorArray[locPtr->power_nation_recno];
570 break;
571 }
572
573 //---- if the command base of the opponent revealed, establish contact ----//
574
575 if( locPtr->is_firm() )
576 {
577 Firm* firmPtr = firm_array[locPtr->firm_recno()];
578
579 if( firmPtr->nation_recno > 0 && nation_array.player_recno )
580 {
581 NationRelation *relation = (~nation_array)->get_relation(firmPtr->nation_recno);
582
583 if( !relation->has_contact )
584 {
585 if( !remote.is_enable() )
586 {
587 (~nation_array)->establish_contact(firmPtr->nation_recno);
588 }
589 else
590 {
591 if( !relation->contact_msg_flag )
592 {
593 // packet structure : <player nation> <explored nation>
594 short *shortPtr = (short *)remote.new_send_queue_msg(MSG_NATION_CONTACT, 2*sizeof(short));
595 *shortPtr = nation_array.player_recno;
596 shortPtr[1] = firmPtr->nation_recno;
597 relation->contact_msg_flag = 1;
598 }
599 }
600 }
601 }
602 }
603
604 if( locPtr->is_town() )
605 {
606 Town* townPtr = town_array[locPtr->town_recno()];
607
608 if( townPtr->nation_recno > 0 && nation_array.player_recno )
609 {
610 NationRelation *relation = (~nation_array)->get_relation(townPtr->nation_recno);
611
612 if( !relation->has_contact )
613 {
614 if( !remote.is_enable() )
615 {
616 (~nation_array)->establish_contact(townPtr->nation_recno);
617 }
618 else
619 {
620 if( !relation->contact_msg_flag )
621 {
622 // packet structure : <player nation> <explored nation>
623 short *shortPtr = (short *)remote.new_send_queue_msg(MSG_NATION_CONTACT, 2*sizeof(short));
624 *shortPtr = nation_array.player_recno;
625 shortPtr[1] = townPtr->nation_recno;
626 relation->contact_msg_flag = 1;
627 }
628 }
629 }
630 }
631 }
632 }
633 }
634 }
635 }
636 //--------- End of function World::explore ---------//
637
638
639 //-------- Begin of function World::is_explored ---------//
640 //
641 // Check if the whole area has been explored or not.
642 //
643 // <int> xLoc1, yLoc1 = the coordination of the area to explore
644 // <int> xLoc2, yLoc2 = the coordination of the area to explore
645 //
is_explored(int xLoc1,int yLoc1,int xLoc2,int yLoc2)646 int World::is_explored(int xLoc1, int yLoc1, int xLoc2, int yLoc2)
647 {
648 if( config.explore_whole_map )
649 return 1;
650
651 int xLoc, yLoc;
652 Location* locPtr;
653
654 for( yLoc=yLoc1 ; yLoc<=yLoc2 ; yLoc++ )
655 {
656 locPtr = get_loc(xLoc1, yLoc);
657
658 for( xLoc=xLoc1 ; xLoc<=xLoc2 ; xLoc++, locPtr++ )
659 {
660 if( !locPtr->explored() )
661 return 0;
662 }
663 }
664
665 return 1;
666 }
667 //--------- End of function World::is_explored ---------//
668
669
670 //----------- Begin of function World::load_map ------------//
671 //
672 // Load a custom map file.
673 //
load_map(char * fileName)674 void World::load_map(char* fileName)
675 {
676 generate_map();
677
678 return;
679
680 //---------- initialize the map matrix --------//
681
682 max_x_loc = 200;
683 max_y_loc = 200;
684
685 loc_matrix = (Location*) mem_resize( loc_matrix , max_x_loc * max_y_loc * sizeof(Location) );
686
687 memset( loc_matrix, 0, sizeof(Location) * max_x_loc * max_y_loc );
688
689 int baseType = TERRAIN_DARK_DIRT;
690
691 int terrainId = terrain_res.scan(baseType, MIDDLE_MASK, baseType, MIDDLE_MASK,
692 baseType, MIDDLE_MASK, baseType, MIDDLE_MASK, 1); // 1-get the first instance
693
694 for( int i=0 ; i<max_x_loc*max_y_loc ; i++ )
695 {
696 loc_matrix[i].terrain_id = terrainId+misc.random(3);
697 }
698
699 assign_map();
700
701 return;
702
703 //---------- initialize the map matrix --------//
704
705 max_x_loc = 120;
706 max_y_loc = 120;
707
708 loc_matrix = (Location*) mem_resize( loc_matrix , max_x_loc * max_y_loc * sizeof(Location) );
709
710 //-------------- read in the map -------------//
711
712 File mapFile;
713
714 mapFile.file_open(fileName);
715
716 mapFile.file_read(loc_matrix, sizeof(Location)*MAX_WORLD_X_LOC*MAX_WORLD_Y_LOC );
717
718 mapFile.file_close();
719
720 //----- assign the map to MapMatrix and ZoomMatrix -----//
721
722 assign_map();
723 }
724 //----------- End of function World::load_map ------------//
725
726
727 //-------- Begin of function World::check_unit_space ------//
728 //
729 // To check whether or not the area bounded by the upper left
730 // corner (xLoc1, yLoc1) and lower right corner (xLoc2, yLoc2)
731 // can be built.
732 //
733 // <int> xLoc1 = the upper left x
734 // <int> yLoc1 = the upper left y
735 // <int> xLoc2 = the lower right x
736 // <int> yLoc2 = the lower right y
737 // [int] mobileType = mobile type (default: UNIT_LAND)
738 // [int] buildFlag = whether the located area is for building a firm/town
739 // if so, the location must no have any raw site.
740 // (default: 0)
741 //
742 // return 1 for true. 0 for false
743 //
check_unit_space(int xLoc1,int yLoc1,int xLoc2,int yLoc2,int mobileType,int buildFlag)744 inline int World::check_unit_space(int xLoc1, int yLoc1, int xLoc2, int yLoc2, int mobileType, int buildFlag)
745 {
746 if(xLoc1<0 || xLoc1>=MAX_WORLD_X_LOC)
747 return 0;
748 if(yLoc1<0 || yLoc1>=MAX_WORLD_Y_LOC)
749 return 0;
750 if(xLoc2<0 || xLoc2>=MAX_WORLD_X_LOC)
751 return 0;
752 if(yLoc2<0 || yLoc2>=MAX_WORLD_Y_LOC)
753 return 0;
754
755 Location* locPtr = world.get_loc(xLoc1, yLoc1);
756 int x, y;
757 int canBuildFlag = 1;
758
759 for(y=yLoc1; y<=yLoc2; y++)
760 {
761 locPtr = world.get_loc(xLoc1, y);
762
763 for(x=xLoc1; x<=xLoc2; x++, locPtr++)
764 {
765 if( !locPtr->can_move(mobileType) ||
766 ( buildFlag && (locPtr->is_power_off() || locPtr->has_site()) ) ) // if build a firm/town, there must not be any sites in the area
767 {
768 canBuildFlag=0;
769 break;
770 }
771 }
772
773 if(canBuildFlag==0)
774 break;
775 }
776
777 if( canBuildFlag )
778 return 1;
779 else
780 return 0;
781 }
782 //-------- End of function World::check_unit_space ------//
783
784
785 //-------- Begin of function World::locate_space ------//
786 //
787 // Locate an area in the world map around the firm to place
788 // the unit
789 //
790 // <int*> xLoc1 = the upper left x location of the building, also for returning the result location
791 // <int*> yLoc1 = the upper left y location of the building
792 // <int> xLoc2 = the lower right x location of the building
793 // <int> yLoc2 = the lower right y location of the building
794 // <int> spaceLocWidth = the location width of the required space
795 // <int> spaceLocHeight = the location height of the required space
796 // [int] mobileType = mobile type (default: UNIT_LAND)
797 // [int] regionId = specify the region no. of the location to locate
798 // (default: region no. of xLoc1, yLoc1)
799 // [int] buildFlag = whether the located area is for building a firm/town
800 // if so, the location must not have any raw site.
801 // (default: 0)
802 //
803 // return : <int> 1 - free space found
804 // 0 - free space not found
805 //
locate_space(int * pxLoc1,int * pyLoc1,int xLoc2,int yLoc2,int spaceLocWidth,int spaceLocHeight,int mobileType,int regionId,int buildFlag)806 int World::locate_space(int* pxLoc1, int* pyLoc1, int xLoc2, int yLoc2,
807 int spaceLocWidth, int spaceLocHeight, int mobileType, int regionId, int buildFlag)
808 {
809 int &xLoc1 = *pxLoc1, &yLoc1 = *pyLoc1;
810
811 if( !regionId )
812 regionId = get_loc(xLoc1, yLoc1)->region_id;
813
814 int isPlateau = get_loc(xLoc1, yLoc1)->is_plateau();
815
816 //-----------------------------------------------------------//
817 // xLoc, yLoc is the adjusted upper left corner location of
818 // the firm. with the adjustment, it is easier to do the following
819 // checking.
820 //-----------------------------------------------------------//
821
822 Location* locPtr;
823 int xLoc = xLoc1 - spaceLocWidth + 1;
824 int yLoc = yLoc1 - spaceLocHeight + 1;
825
826 if(xLoc < 0)
827 xLoc = 0;
828 if(yLoc < 0)
829 yLoc = 0;
830
831 int width = xLoc2 - xLoc + 1;
832 int height = yLoc2 - yLoc + 1;
833 int loopCount=0;
834
835 while(1)
836 {
837 err_when( ++loopCount > MAX_WORLD_X_LOC * MAX_WORLD_Y_LOC * 4 );
838
839 //-----------------------------------------------------------//
840 // step 1
841 //-----------------------------------------------------------//
842 int xOffset = width/2;
843 int yOffset = height;
844 int x, y;
845
846 x = xLoc + xOffset;
847 y = yLoc + yOffset;
848
849 if(x>=0 && y>=0 && x+spaceLocWidth-1<MAX_WORLD_X_LOC && y+spaceLocHeight-1<MAX_WORLD_Y_LOC)
850 {
851 if(mobileType==UNIT_LAND || (x%2==0 && y%2==0))
852 {
853 locPtr = get_loc(x,y);
854
855 if( locPtr->region_id == regionId &&
856 locPtr->is_plateau() == isPlateau &&
857 check_unit_space(x, y, x+spaceLocWidth-1, y+spaceLocHeight-1, mobileType, buildFlag))
858 {
859 xLoc1 = x;
860 yLoc1 = y;
861 return 1;
862 }
863 }
864 }
865
866 int sign = -1;
867 int i, j, k, limit;
868
869 //-----------------------------------------------------------//
870 // step 2
871 //-----------------------------------------------------------//
872 //y = yLoc + yOffset;
873 limit = width + 2;
874 for(i=1; i<limit; i++)
875 {
876 xOffset += sign * i;
877 x = xLoc + xOffset;
878
879 if(x>=0 && y>=0 && x+spaceLocWidth-1<MAX_WORLD_X_LOC && y+spaceLocHeight-1<MAX_WORLD_Y_LOC)
880 {
881 if(mobileType==UNIT_LAND || (x%2==0 && y%2==0))
882 {
883 locPtr = get_loc(x,y);
884
885 if( locPtr->region_id == regionId &&
886 locPtr->is_plateau() == isPlateau &&
887 check_unit_space(x, y, x+spaceLocWidth-1, y+spaceLocHeight-1, mobileType, buildFlag))
888 {
889 xLoc1 = x;
890 yLoc1 = y;
891 return 1;
892 }
893 }
894 }
895
896 sign *= -1;
897 }
898
899 //-----------------------------------------------------------//
900 // step 3
901 //-----------------------------------------------------------//
902 i = limit-1;
903
904 limit = (height+1)*2;
905 int r = sign*i;
906 int lastX = xOffset;
907 //int lastY = yOffset;
908
909 for(j=0; j<limit; j++)
910 {
911 if(j%2)
912 {
913 //x = xLoc + lastX;
914 xOffset = lastX;
915 x = xLoc + xOffset;
916 //y = yLoc + yOffset;
917
918 if(x>=0 && y>=0 && x+spaceLocWidth-1<MAX_WORLD_X_LOC && y+spaceLocHeight-1<MAX_WORLD_Y_LOC)
919 {
920 if(mobileType==UNIT_LAND || (x%2==0 && y%2==0))
921 {
922 locPtr = get_loc(x,y);
923
924 if( locPtr->region_id == regionId &&
925 locPtr->is_plateau() == isPlateau &&
926 check_unit_space(x, y, x+spaceLocWidth-1, y+spaceLocHeight-1, mobileType, buildFlag))
927 {
928 xLoc1 = x;
929 yLoc1 = y;
930 return 1;
931 }
932 }
933 }
934 }
935 else
936 {
937 xOffset = lastX + r;
938 yOffset--;
939
940 x = xLoc + xOffset;
941 y = yLoc + yOffset;
942
943 if(x>=0 && y>=0 && x+spaceLocWidth-1<MAX_WORLD_X_LOC && y+spaceLocHeight-1<MAX_WORLD_Y_LOC)
944 {
945 if(mobileType==UNIT_LAND || (x%2==0 && y%2==0))
946 {
947 locPtr = get_loc(x,y);
948
949 if( locPtr->region_id == regionId &&
950 locPtr->is_plateau() == isPlateau &&
951 check_unit_space(x, y, x+spaceLocWidth-1, y+spaceLocHeight-1, mobileType, buildFlag))
952 {
953 xLoc1 = x;
954 yLoc1 = y;
955 return 1;
956 }
957 }
958 }
959 }
960 }
961
962 //-----------------------------------------------------------//
963 // step 4
964 //-----------------------------------------------------------//
965 y = yLoc + yOffset;
966 for(k=0; k<=width; k++)
967 {
968 sign *= -1;
969 i--;
970 r = sign*i;
971 xOffset -= r;
972
973 x = xLoc + xOffset;
974
975 if(x>=0 && y>=0 && x+spaceLocWidth-1<MAX_WORLD_X_LOC && y+spaceLocHeight-1<MAX_WORLD_Y_LOC)
976 {
977 if(mobileType==UNIT_LAND || (x%2==0 && y%2==0))
978 {
979 locPtr = get_loc(x,y);
980
981 if( locPtr->region_id == regionId &&
982 locPtr->is_plateau() == isPlateau &&
983 check_unit_space(x, y, x+spaceLocWidth-1, y+spaceLocHeight-1, mobileType, buildFlag))
984 {
985 xLoc1 = x;
986 yLoc1 = y;
987 return 1;
988 }
989 }
990 }
991 }
992
993 //-----------------------------------------------------------//
994 // re-init the parameters
995 //-----------------------------------------------------------//
996 if(xLoc<=0 && yLoc<=0 && width>=MAX_WORLD_X_LOC && height>=MAX_WORLD_Y_LOC)
997 break; // the whole map has been checked
998
999 width += 2;
1000 height += 2;
1001
1002 xLoc -= 1;
1003 yLoc -= 1;
1004 if(xLoc<0)
1005 {
1006 xLoc = 0;
1007 width--;
1008 }
1009 if(yLoc<0)
1010 {
1011 yLoc=0;
1012 height--;
1013 }
1014
1015 if(xLoc+width>MAX_WORLD_X_LOC)
1016 width--;
1017 if(yLoc+height>MAX_WORLD_Y_LOC)
1018 height--;
1019
1020 //if(width==xLoc2-xLoc1+spaceLocWidth && height==yLoc2-yLoc1+spaceLocHeight) // terminate the checking
1021 // return 0;
1022 }
1023
1024 return 0;
1025 }
1026 //-------- End of function World::locate_space ------//
1027
1028
1029 //-------- Begin of function World::locate_space_random ------//
1030 //
1031 // Locate an area of space in the world map randomly. Pick any
1032 // space available in that area without a specific scanning order.
1033 //
1034 // <int&> xLoc1 = the scaning range, also for returning the result location
1035 // <int&> yLoc1 = the scaning range
1036 // <int> xLoc2 = the scaning range
1037 // <int> yLoc2 = the scaning range
1038 // <int> spaceLocWidth = the location width of the required space
1039 // <int> spaceLocHeight = the location height of the required space
1040 // <int> maxTries = maximum no. of tries
1041 // [int] regionId = if this is specified, the result location will
1042 // be in this region.
1043 // [int] buildSite = whether locating space for building a site
1044 // (default: 0)
1045 // [char] teraMask = terrain mask (default: 1)
1046 //
1047 // return : <int> 1 - free space found
1048 // 0 - free space found
1049 //
locate_space_random(int & xLoc1,int & yLoc1,int xLoc2,int yLoc2,int spaceLocWidth,int spaceLocHeight,int maxTries,int regionId,int buildSite,char teraMask)1050 int World::locate_space_random(int& xLoc1, int& yLoc1, int xLoc2, int yLoc2,
1051 int spaceLocWidth, int spaceLocHeight, int maxTries,
1052 int regionId, int buildSite, char teraMask)
1053 {
1054 int i, x, y, xTemp, xLoc, yLoc, canBuildFlag;
1055 int scanWidth = xLoc2-xLoc1-spaceLocWidth+2; //xLoc2-xLoc1+1-spaceLocWidth+1;
1056 int scanHeight = yLoc2-yLoc1-spaceLocHeight+2; //yLoc2-yLoc1+1-spaceLocHeight+1;
1057 Location* locPtr;
1058
1059 for( i=0 ; i<maxTries ; i++ )
1060 {
1061 xLoc = xLoc1 + misc.random(scanWidth);
1062 yLoc = yLoc1 + misc.random(scanHeight);
1063 canBuildFlag=1;
1064
1065 //---------- check if the area is all free ----------//
1066
1067 xTemp = xLoc+spaceLocWidth-1;
1068
1069 for( y=yLoc+spaceLocHeight-1; y>=yLoc; y-- )
1070 {
1071 locPtr = world.get_loc(xTemp, y);
1072
1073 for(x=xTemp; x>=xLoc; x--, locPtr-- )
1074 {
1075 if( ( buildSite ? !locPtr->can_build_site(teraMask) : !locPtr->can_build_firm(teraMask) ) ||
1076 locPtr->is_power_off() )
1077 {
1078 canBuildFlag=0;
1079 break;
1080 }
1081 }
1082
1083 if(!canBuildFlag)
1084 break;
1085 }
1086
1087 if( !canBuildFlag )
1088 continue;
1089
1090 //------ check region id. ------------//
1091
1092 locPtr = world.get_loc(xLoc, yLoc);
1093
1094 if( regionId && locPtr->region_id != regionId )
1095 continue;
1096
1097 //------------------------------------//
1098
1099 xLoc1 = xLoc;
1100 yLoc1 = yLoc;
1101
1102 err_when(buildSite && !locPtr->can_build_site(teraMask));//-*** hard codes for mine size 3x3
1103 return 1;
1104 }
1105
1106 return 0;
1107 }
1108 //-------- End of function World::locate_space_random ------//
1109
1110
1111 //-------- Begin of function World::can_build_firm ---------//
1112 //
1113 // Check if it is free to construct a building on the specific area.
1114 //
1115 // <int> xLoc1, yLoc1 = the coordination of the area to can_build
1116 // <int> firmId = id. of the firm
1117 // [short] unitRecno = the unit recno of the unit to build the firm
1118 // if the builder unit stands on the building area, still consider the area as buildable
1119 // (default: -1, do not take the builder into account)
1120 //
can_build_firm(int xLoc1,int yLoc1,int firmId,short unitRecno)1121 int World::can_build_firm(int xLoc1, int yLoc1, int firmId, short unitRecno)
1122 {
1123 if( xLoc1 < 0 || yLoc1 < 0 || xLoc1 > MAX_WORLD_X_LOC || yLoc1 > MAX_WORLD_Y_LOC )
1124 return 0;
1125
1126 //------------------------------------------//
1127
1128 FirmInfo* firmInfo = firm_res[firmId];
1129
1130 int xLoc, yLoc;
1131 int xLoc2 = xLoc1 + firmInfo->loc_width - 1;
1132 int yLoc2 = yLoc1 + firmInfo->loc_height - 1;
1133 if(xLoc2>=max_x_loc || yLoc2>max_y_loc)
1134 return 0;
1135
1136 Location* locPtr;
1137 char teraMask, pierFlag;
1138
1139 switch(firmInfo->tera_type)
1140 {
1141 case 1: // default : land firm
1142 case 2: // sea firm
1143 case 3: // land or sea firm
1144 teraMask = firmInfo->tera_type;
1145 for( yLoc=yLoc1 ; yLoc<=yLoc2 ; yLoc++ )
1146 {
1147 locPtr = get_loc(xLoc1, yLoc);
1148
1149 for( xLoc=xLoc1 ; xLoc<=xLoc2 ; xLoc++, locPtr++ )
1150 {
1151 // ##### patch begin Gilbert 14/3 ######//
1152 if(!locPtr->can_build_firm(teraMask) &&
1153 (!locPtr->has_unit(UNIT_LAND) || locPtr->unit_recno(UNIT_LAND)!=unitRecno))
1154 return 0;
1155 // ##### patch end Gilbert 14/3 ######//
1156
1157 if( firmId != FIRM_MINE && locPtr->has_site() ) // don't allow building any buildings other than mines on a location with a site
1158 return 0;
1159 }
1160 }
1161 return 1;
1162
1163 case 4: // special firm, such as harbor
1164 // must be 3x3,
1165 // centre square of one side is land (teraMask=1),
1166 // two squares on that side can be land or sea (teraMask=3)
1167 // and other (6 squares) are sea (teraMask=2)
1168 if( firmInfo->loc_width != 3 ||
1169 firmInfo->loc_height != 3)
1170 return 0;
1171
1172 pierFlag = 1|2|4|8; // bit0=north, bit1=south, bit2=west, bit3=east
1173 for( yLoc=yLoc1 ; yLoc<=yLoc2 ; yLoc++ )
1174 {
1175 locPtr = get_loc(xLoc1, yLoc);
1176
1177 for( xLoc=xLoc1 ; xLoc<=xLoc2 ; xLoc++, locPtr++ )
1178 {
1179 if( locPtr->has_site() ) // don't allow building any buildings other than mines on a location with a site
1180 return 0;
1181
1182 static char northPierTera[3][3] = { {2,2,2},{2,2,2},{3,1,3} };
1183 static char southPierTera[3][3] = { {3,1,3},{2,2,2},{2,2,2} };
1184 static char westPierTera[3][3] = { {2,2,3},{2,2,1},{2,2,3} };
1185 static char eastPierTera[3][3] = { {3,2,2},{1,2,2},{3,2,2} };
1186 int x = xLoc - xLoc1;
1187 int y = yLoc - yLoc1;
1188 if(!locPtr->can_build_harbor(northPierTera[y][x]) )
1189 pierFlag &= ~1;
1190 if(!locPtr->can_build_harbor(southPierTera[y][x]) )
1191 pierFlag &= ~2;
1192 if(!locPtr->can_build_harbor(westPierTera[y][x]) )
1193 pierFlag &= ~4;
1194 if(!locPtr->can_build_harbor(eastPierTera[y][x]) )
1195 pierFlag &= ~8;
1196 }
1197 }
1198 err_when( pierFlag != 0 && pierFlag != 1 && pierFlag != 2 &&
1199 pierFlag != 4 && pierFlag != 8 );
1200 return pierFlag;
1201 break;
1202
1203 // other tera_type here
1204
1205 default:
1206 err_here();
1207 return 0;
1208 }
1209 }
1210 //--------- End of function World::can_build_firm ---------//
1211
1212
1213 //-------- Begin of function World::can_build_town ---------//
1214 //
1215 // <int> xLoc1, yLoc1 = the coordination of the area to can_build
1216 // [short] unitRecno = the unit recno of the unit to build the town
1217 // if the builder unit stands on the building area, still consider the area as buildable
1218 // (default: -1, do not take the builder into account)
1219 //
can_build_town(int xLoc1,int yLoc1,short unitRecno)1220 int World::can_build_town(int xLoc1, int yLoc1, short unitRecno)
1221 {
1222 int xLoc, yLoc;
1223 int xLoc2 = xLoc1 + STD_TOWN_LOC_WIDTH - 1;
1224 int yLoc2 = yLoc1 + STD_TOWN_LOC_HEIGHT - 1;
1225
1226 if(xLoc2>=max_x_loc || yLoc2>=max_y_loc)
1227 return 0;
1228
1229 Location* locPtr;
1230
1231 for( yLoc=yLoc1 ; yLoc<=yLoc2 ; yLoc++ )
1232 {
1233 locPtr = get_loc(xLoc1, yLoc);
1234
1235 for( xLoc=xLoc1 ; xLoc<=xLoc2 ; xLoc++, locPtr++ )
1236 {
1237 // ##### patch begin Gilbert 14/3 ######//
1238 // allow the building unit to stand in the area
1239 if( !locPtr->can_build_town() &&
1240 (!locPtr->has_unit(UNIT_LAND) || locPtr->unit_recno(UNIT_LAND)!=unitRecno) )
1241 return 0;
1242 // ##### patch end Gilbert 14/3 ######//
1243 }
1244 }
1245
1246 return 1;
1247 }
1248 //--------- End of function World::can_build_town ---------//
1249
1250
1251 //-------- Begin of function World::can_build_wall ---------//
1252 //
1253 // <int> xLoc, yLoc = the coordination of the area to can_build
1254 // <int> nationRecno = recno of the builder nation.
1255 //
can_build_wall(int xLoc,int yLoc,short nationRecno)1256 int World::can_build_wall(int xLoc, int yLoc, short nationRecno)
1257 {
1258 Location* locPtr = get_loc(xLoc, yLoc);
1259
1260 return locPtr->can_build_wall() && locPtr->power_nation_recno == nationRecno;
1261 }
1262 //--------- End of function World::can_build_wall ---------//
1263
1264
1265 //-------- Begin of function World::can_destruct_wall ---------//
1266 //
1267 // <int> xLoc, yLoc = the coordination of the area to can_build
1268 // <int> nationRecno = recno of the builder nation.
1269 //
can_destruct_wall(int xLoc,int yLoc,short nationRecno)1270 int World::can_destruct_wall(int xLoc, int yLoc, short nationRecno)
1271 {
1272 Location* locPtr = get_loc(xLoc, yLoc);
1273
1274 return locPtr->is_wall() && locPtr->power_nation_recno == nationRecno;
1275 }
1276 //--------- End of function World::can_destruct_wall ---------//
1277
1278
1279 //---------- Begin of function World::draw_link_line -----------//
1280 //
1281 // <int> srcFirmId - id. of the source firm.
1282 // 0 if the source is a town
1283 // <int> srcTownRecno - town recno of the source town
1284 // 0 if the source is a firm
1285 // <int> srcXLoc1, srcYLoc1 - the location of the source area
1286 // srcXLoc2, srcYLoc2
1287 //
1288 // [int] giveEffectiveDis - use this value as the effective distance if this is given
1289 // (default: 0)
1290 //
draw_link_line(int srcFirmId,int srcTownRecno,int srcXLoc1,int srcYLoc1,int srcXLoc2,int srcYLoc2,int givenEffectiveDis)1291 void World::draw_link_line(int srcFirmId, int srcTownRecno, int srcXLoc1,
1292 int srcYLoc1, int srcXLoc2, int srcYLoc2, int givenEffectiveDis)
1293 {
1294 if( srcFirmId == FIRM_INN ) // FirmInn's link is only for scan for neighbor inns quickly, the link line is not displayed
1295 return;
1296
1297 //--------------------------------------//
1298
1299 int srcXLoc = (srcXLoc1 + srcXLoc2)/2;
1300 int srcYLoc = (srcYLoc1 + srcYLoc2)/2;
1301
1302 int srcX = ( ZOOM_X1 + (srcXLoc1-zoom_matrix->top_x_loc) * ZOOM_LOC_WIDTH
1303 + ZOOM_X1 + (srcXLoc2-zoom_matrix->top_x_loc+1) * ZOOM_LOC_WIDTH ) / 2;
1304
1305 int srcY = ( ZOOM_Y1 + (srcYLoc1-zoom_matrix->top_y_loc) * ZOOM_LOC_HEIGHT
1306 + ZOOM_Y1 + (srcYLoc2-zoom_matrix->top_y_loc+1) * ZOOM_LOC_HEIGHT ) / 2;
1307
1308 //------- draw lines connected to town ---------//
1309
1310 int i, townX, townY, effectiveDis;
1311 Town* townPtr;
1312
1313 if( givenEffectiveDis )
1314 effectiveDis = givenEffectiveDis;
1315 else
1316 {
1317 if( srcFirmId )
1318 effectiveDis = EFFECTIVE_FIRM_TOWN_DISTANCE;
1319 else
1320 effectiveDis = EFFECTIVE_TOWN_TOWN_DISTANCE;
1321 }
1322
1323 if( !srcFirmId || firm_res[srcFirmId]->is_linkable_to_town ) // don't draw link line to town if it's an inn
1324 {
1325 for( i=town_array.size() ; i>0 ; i-- )
1326 {
1327 if( town_array.is_deleted(i) )
1328 continue;
1329
1330 townPtr = town_array[i];
1331
1332 if( srcTownRecno && townPtr->town_recno != srcTownRecno )
1333 continue;
1334
1335 //-------- check the distance --------//
1336
1337 if( misc.points_distance( townPtr->center_x, townPtr->center_y,
1338 srcXLoc, srcYLoc ) > effectiveDis )
1339 {
1340 continue;
1341 }
1342
1343 //------ check if both are on the same terrain type ------//
1344
1345 if( (world.get_loc(townPtr->center_x, townPtr->center_y)->is_plateau()==1)
1346 != (world.get_loc(srcXLoc, srcYLoc)->is_plateau()==1) )
1347 {
1348 continue;
1349 }
1350
1351 //---------- draw line now -----------//
1352
1353 townX = ( ZOOM_X1 + (townPtr->loc_x1-zoom_matrix->top_x_loc) * ZOOM_LOC_WIDTH
1354 + ZOOM_X1 + (townPtr->loc_x2-zoom_matrix->top_x_loc+1) * ZOOM_LOC_WIDTH ) / 2;
1355
1356 townY = ( ZOOM_Y1 + (townPtr->loc_y1-zoom_matrix->top_y_loc) * ZOOM_LOC_HEIGHT
1357 + ZOOM_Y1 + (townPtr->loc_y2-zoom_matrix->top_y_loc+1) * ZOOM_LOC_HEIGHT ) / 2;
1358
1359 anim_line.draw_line(&vga_back, srcX, srcY, townX, townY);
1360 }
1361 }
1362
1363 //------- draw lines connected to firms ---------//
1364
1365 if( givenEffectiveDis )
1366 effectiveDis = givenEffectiveDis;
1367 else
1368 {
1369 if( srcFirmId )
1370 effectiveDis = EFFECTIVE_FIRM_FIRM_DISTANCE;
1371 else
1372 effectiveDis = EFFECTIVE_FIRM_TOWN_DISTANCE;
1373 }
1374
1375 int firmX, firmY, linkFlag;
1376 Firm* firmPtr;
1377
1378 for( i=firm_array.size() ; i>0 ; i-- )
1379 {
1380 if( firm_array.is_deleted(i) )
1381 continue;
1382
1383 firmPtr = firm_array[i];
1384
1385 //------ only link if the firms have relationship -----//
1386
1387 if( srcFirmId )
1388 linkFlag = firm_res[firmPtr->firm_id]->is_linkable_to_firm(srcFirmId);
1389 else
1390 linkFlag = firm_res[firmPtr->firm_id]->is_linkable_to_town;
1391
1392 if( !linkFlag )
1393 continue;
1394
1395 //-------- check the distance --------//
1396
1397 if( misc.points_distance( firmPtr->center_x, firmPtr->center_y,
1398 srcXLoc, srcYLoc ) > effectiveDis )
1399 {
1400 continue;
1401 }
1402
1403 //------ check if both are on the same terrain type ------//
1404
1405 if( (world.get_loc(firmPtr->center_x, firmPtr->center_y)->is_plateau()==1)
1406 != (world.get_loc(srcXLoc, srcYLoc)->is_plateau()==1) )
1407 {
1408 continue;
1409 }
1410
1411 //---------- draw line now -----------//
1412
1413 firmX = ( ZOOM_X1 + (firmPtr->loc_x1-zoom_matrix->top_x_loc) * ZOOM_LOC_WIDTH
1414 + ZOOM_X1 + (firmPtr->loc_x2-zoom_matrix->top_x_loc+1) * ZOOM_LOC_WIDTH ) / 2;
1415
1416 firmY = ( ZOOM_Y1 + (firmPtr->loc_y1-zoom_matrix->top_y_loc) * ZOOM_LOC_HEIGHT
1417 + ZOOM_Y1 + (firmPtr->loc_y2-zoom_matrix->top_y_loc+1) * ZOOM_LOC_HEIGHT ) / 2;
1418
1419 anim_line.draw_line(&vga_back, srcX, srcY, firmX, firmY);
1420 }
1421 }
1422 //----------- End of function World::draw_link_line ------------//
1423
1424
1425 //-------- Begin of function World::set_surr_power_off ---------//
set_surr_power_off(int xLoc,int yLoc)1426 void World::set_surr_power_off(int xLoc, int yLoc)
1427 {
1428 if(xLoc>0) // west
1429 get_loc(xLoc-1, yLoc)->set_power_off();
1430
1431 if(xLoc<max_x_loc-1)
1432 get_loc(xLoc+1, yLoc)->set_power_off();
1433
1434 if(yLoc>0) // north
1435 get_loc(xLoc, yLoc-1)->set_power_off();
1436
1437 if(yLoc<max_y_loc-1) // south
1438 get_loc(xLoc, yLoc+1)->set_power_off();
1439 }
1440 //----------- End of function World::set_surr_power_off ------------//
1441
1442
1443 //-------- Begin of function World::set_all_power ---------//
1444 //
set_all_power()1445 void World::set_all_power()
1446 {
1447 //--------- set town's influence -----------//
1448
1449 Town* townPtr;
1450 int i;
1451
1452 for( i=town_array.size() ; i>0 ; i-- )
1453 {
1454 if( town_array.is_deleted(i) )
1455 continue;
1456
1457 townPtr = town_array[i];
1458
1459 if( !townPtr->nation_recno )
1460 continue;
1461
1462 //------- set the influence range of this town -----//
1463
1464 set_power(townPtr->loc_x1, townPtr->loc_y1, townPtr->loc_x2, townPtr->loc_y2, (char)townPtr->nation_recno);
1465 }
1466
1467 //--------- set firm's influence -----------//
1468
1469 Firm* firmPtr;
1470
1471 for( i=firm_array.size() ; i>0 ; i-- )
1472 {
1473 if( firm_array.is_deleted(i) )
1474 continue;
1475
1476 firmPtr = firm_array[i];
1477
1478 if( !firmPtr->nation_recno )
1479 continue;
1480
1481 if( !firmPtr->should_set_power )
1482 continue;
1483
1484 //------- set the influence range of this firm -----//
1485
1486 set_power(firmPtr->loc_x1, firmPtr->loc_y1, firmPtr->loc_x2, firmPtr->loc_y2, (char)firmPtr->nation_recno);
1487 }
1488 }
1489 //--------- End of function World::set_all_power ---------//
1490
1491
1492 //-------- Begin of function World::set_power ---------//
1493 //
1494 // <int> xLoc1, yLoc1, - area on the map which the power should be set
1495 // xLoc2, yLoc2
1496 //
1497 // <int> nationRcno - nation recno
1498 //
set_power(int xLoc1,int yLoc1,int xLoc2,int yLoc2,int nationRecno)1499 void World::set_power(int xLoc1, int yLoc1, int xLoc2, int yLoc2, int nationRecno)
1500 {
1501 //------- reset power_nation_recno first ------//
1502
1503 int plateauResult = (get_loc((xLoc1+xLoc2)/2, (yLoc1+yLoc2)/2)->is_plateau()==1);
1504
1505 int xLoc, yLoc, centerY, t;
1506 Location* locPtr = loc_matrix;
1507
1508 xLoc1 = MAX( 0, xLoc1 - EFFECTIVE_POWER_DISTANCE+1);
1509 yLoc1 = MAX( 0, yLoc1 - EFFECTIVE_POWER_DISTANCE+1);
1510 xLoc2 = MIN( MAX_WORLD_X_LOC-1, xLoc2 + EFFECTIVE_POWER_DISTANCE-1);
1511 yLoc2 = MIN( MAX_WORLD_Y_LOC-1, yLoc2 + EFFECTIVE_POWER_DISTANCE-1);
1512
1513 centerY = (yLoc1+yLoc2) / 2;
1514
1515 for( yLoc=yLoc1 ; yLoc<=yLoc2 ; yLoc++ )
1516 {
1517 t=abs(yLoc-centerY)/2;
1518
1519 for( xLoc=xLoc1+t ; xLoc<=xLoc2-t ; xLoc++, locPtr++ )
1520 {
1521 locPtr = get_loc(xLoc, yLoc);
1522
1523 if(locPtr->sailable())//if(!locPtr->walkable())
1524 continue;
1525
1526 if(locPtr->is_power_off())
1527 continue;
1528
1529 if((locPtr->is_plateau()==1) != plateauResult)
1530 continue;
1531
1532 if(locPtr->power_nation_recno==0)
1533 {
1534 locPtr->power_nation_recno = nationRecno;
1535 sys.map_need_redraw = 1; // request redrawing the map next time
1536 }
1537 }
1538 }
1539 }
1540 //--------- End of function World::set_power ---------//
1541
1542
1543 //-------- Begin of function World::restore_power ---------//
1544 //
1545 // <int> xLoc1, yLoc1, - area on the map which the power should be restored
1546 // xLoc2, yLoc2
1547 //
1548 // <int> townRecno, firmRecno - either one
1549 //
restore_power(int xLoc1,int yLoc1,int xLoc2,int yLoc2,int townRecno,int firmRecno)1550 void World::restore_power(int xLoc1, int yLoc1, int xLoc2, int yLoc2, int townRecno, int firmRecno)
1551 {
1552 int nationRecno;
1553
1554 if( townRecno )
1555 {
1556 nationRecno = town_array[townRecno]->nation_recno;
1557 town_array[townRecno]->nation_recno = 0;
1558 }
1559
1560 if( firmRecno )
1561 {
1562 nationRecno = firm_array[firmRecno]->nation_recno;
1563 firm_array[firmRecno]->nation_recno = 0;
1564 }
1565
1566 //------- reset power_nation_recno first ------//
1567
1568 int xLoc, yLoc, centerY, t;
1569 Location* locPtr = loc_matrix;
1570
1571 xLoc1 = MAX( 0, xLoc1 - EFFECTIVE_POWER_DISTANCE+1);
1572 yLoc1 = MAX( 0, yLoc1 - EFFECTIVE_POWER_DISTANCE+1);
1573 xLoc2 = MIN( MAX_WORLD_X_LOC-1, xLoc2 + EFFECTIVE_POWER_DISTANCE-1);
1574 yLoc2 = MIN( MAX_WORLD_Y_LOC-1, yLoc2 + EFFECTIVE_POWER_DISTANCE-1);
1575
1576 centerY = (yLoc1+yLoc2) / 2;
1577
1578 for( yLoc=yLoc1 ; yLoc<=yLoc2 ; yLoc++ )
1579 {
1580 t=abs(yLoc-centerY)/2;
1581
1582 for( xLoc=xLoc1+t ; xLoc<=xLoc2-t ; xLoc++, locPtr++ )
1583 {
1584 locPtr = get_loc(xLoc, yLoc);
1585
1586 if( locPtr->power_nation_recno==nationRecno )
1587 {
1588 locPtr->power_nation_recno = 0;
1589 sys.map_need_redraw = 1; // request redrawing the map next time
1590 }
1591 }
1592 }
1593
1594 //--- if some power areas are freed up, see if neighbor towns/firms should take up these power areas ----//
1595
1596 if( sys.map_need_redraw ) // when calls set_all_power(), the nation_recno of the calling firm must be reset
1597 set_all_power();
1598
1599 //------- restore the nation recno of the calling town/firm -------//
1600
1601 if( townRecno )
1602 town_array[townRecno]->nation_recno = nationRecno;
1603
1604 if( firmRecno )
1605 firm_array[firmRecno]->nation_recno = nationRecno;
1606 }
1607 //--------- End of function World::restore_power ---------//
1608
1609
1610 //-------- Begin of function World::detect_firm_town ---------//
1611 //
detect_firm_town()1612 int World::detect_firm_town()
1613 {
1614 // ##### begin Gilbert 19/9 ########//
1615 // int rc = mouse.single_click(ZOOM_X1, ZOOM_Y1, ZOOM_X2, ZOOM_Y2, 2);
1616 if( !mouse.any_click(ZOOM_X1, ZOOM_Y1, ZOOM_X2, ZOOM_Y2, 2) )
1617 return 0;
1618 // ##### end Gilbert 19/9 ########//
1619
1620 //------ detect pressing on link enable/disable sign -----//
1621
1622 Firm* firmPtr;
1623
1624 if( firm_array.selected_recno )
1625 {
1626 firmPtr = firm_array[firm_array.selected_recno];
1627
1628 if( firmPtr->should_show_info() && // only if should_show_info() is 1, we can detect links from this firm (it is not limited to player firms, as firms with player's workers should be allowed for resigning the player worker from the firm
1629 firmPtr->draw_detect_link_line(1) ) // 1-detect action
1630 {
1631 return 1;
1632 }
1633 }
1634
1635 Town* townPtr;
1636
1637 if( town_array.selected_recno )
1638 {
1639 townPtr = town_array[town_array.selected_recno];
1640
1641 if( townPtr->nation_recno==nation_array.player_recno &&
1642 townPtr->draw_detect_link_line(1) ) // 1-detect action
1643 {
1644 return 1;
1645 }
1646 }
1647
1648 // ####### begin Gilbert 12/9 #########// see Power::detect_select
1649 /*
1650 //--------------- detect firm ------------------//
1651
1652 if( rc==1 ) // left click
1653 {
1654 int mouseAbsX = mouse.cur_x - ZOOM_X1 + World::view_top_x;
1655 int mouseAbsY = mouse.cur_y - ZOOM_Y1 + World::view_top_y;
1656
1657 int i;
1658
1659 for( i=firm_array.size() ; i>0 ; i-- )
1660 {
1661 if( firm_array.is_deleted(i) )
1662 continue;
1663
1664 firmPtr = firm_array[i];
1665
1666 if( misc.is_touch( mouseAbsX, mouseAbsY, mouseAbsX, mouseAbsY,
1667 firmPtr->abs_x1, firmPtr->abs_y1, firmPtr->abs_x2, firmPtr->abs_y2 ) )
1668 {
1669 power.reset_selection();
1670 firm_array.selected_recno = i;
1671 firmPtr->sort_worker();
1672 info.disp();
1673
1674 // -------- sound effect -----------//
1675
1676 if( firmPtr->nation_recno == nation_array.player_recno && se_res.mark_select_object_time() )
1677 {
1678 se_res.sound(firmPtr->center_x, firmPtr->center_y, 1,
1679 'F', firmPtr->firm_id, firmPtr->under_construction ? "SELU" : "SEL" );
1680 }
1681 return 1;
1682 }
1683 }
1684
1685 //----------- detect town section --------------//
1686
1687 for( i=town_array.size() ; i>0 ; i-- )
1688 {
1689 if( town_array.is_deleted(i) )
1690 continue;
1691
1692 townPtr = town_array[i];
1693
1694 if( misc.is_touch( mouseAbsX, mouseAbsY, mouseAbsX, mouseAbsY,
1695 townPtr->abs_x1, townPtr->abs_y1, townPtr->abs_x2, townPtr->abs_y2 ) )
1696 {
1697 power.reset_selection();
1698 town_array.selected_recno = i;
1699 info.disp();
1700
1701 // -------- sound effect -----------//
1702
1703 if( townPtr->nation_recno == nation_array.player_recno
1704 && se_res.mark_select_object_time() )
1705 {
1706 se_res.sound(townPtr->center_x, townPtr->center_y, 1,
1707 'T', 0, "SEL" );
1708 }
1709 return 1;
1710 }
1711 }
1712 }
1713 */
1714
1715 return 0;
1716 }
1717 //-------- End of function World::detect_firm_town ---------//
1718
1719
1720 //-------- Begin of function World::earth_equake ------//
earth_quake()1721 void World::earth_quake()
1722 {
1723 Location *locPtr;
1724 int x,y;
1725 for(y = 0; y < max_y_loc; ++y)
1726 {
1727 locPtr = get_loc(0,y);
1728 for( x = 0; x < max_x_loc; ++x, ++locPtr)
1729 {
1730 if(locPtr->is_wall() )
1731 {
1732 locPtr->attack_wall( weather.quake_rate(x,y) /2 );
1733 }
1734 }
1735 }
1736
1737 int firmDamage = 0;
1738 int firmDie = 0;
1739 int i;
1740 for( i=firm_array.size() ; i>0 ; i-- )
1741 {
1742 if( firm_array.is_deleted(i) || !firm_res[firm_array[i]->firm_id]->buildable)
1743 continue;
1744
1745 Firm *firmPtr = firm_array[i];
1746 x = firmPtr->center_x;
1747 y = firmPtr->center_y;
1748 firmPtr->hit_points -= weather.quake_rate(x,y);
1749 if( firmPtr->own_firm() )
1750 firmDamage++;
1751 if( firmPtr->hit_points <= 0)
1752 {
1753 firmPtr->hit_points = (float) 0;
1754 if( firmPtr->own_firm() )
1755 firmDie++;
1756 se_res.sound(firmPtr->center_x, firmPtr->center_y, 1,
1757 'F', firmPtr->firm_id, "DIE" );
1758 firm_array.del_firm(i);
1759 }
1760 }
1761
1762 int townDamage = 0;
1763 for( i=town_array.size() ; i>0 ; i-- )
1764 {
1765 if( town_array.is_deleted(i) )
1766 continue;
1767
1768 Town *townPtr = town_array[i];
1769 int ownTown = townPtr->nation_recno == nation_array.player_recno;
1770 short beforePopulation = townPtr->population;
1771 short causalty = weather.quake_rate(townPtr->center_x, townPtr->center_y) / 10;
1772 for( ; causalty > 0 && !town_array.is_deleted(i); --causalty )
1773 {
1774 townPtr->kill_town_people(0);
1775 }
1776 if( town_array.is_deleted(i) )
1777 causalty = beforePopulation;
1778 else
1779 causalty = beforePopulation - townPtr->population;
1780
1781 if(ownTown)
1782 townDamage += causalty;
1783 }
1784
1785 int unitDamage = 0;
1786 int unitDie = 0;
1787 for( i=unit_array.size(); i > 0; i-- )
1788 {
1789 if( unit_array.is_deleted(i))
1790 continue;
1791
1792 Unit *unitPtr = unit_array[i];
1793
1794 // ###### begin Gilbert 30/8 ######//
1795 // no damage to air unit , sea unit or overseer
1796 if( !unitPtr->is_visible() || unitPtr->mobile_type == UNIT_AIR
1797 || unitPtr->mobile_type == UNIT_SEA)
1798 continue;
1799 // ###### end Gilbert 30/8 ######//
1800
1801 float damage = (float) weather.quake_rate(unitPtr->cur_x_loc(),unitPtr->cur_y_loc() ) *
1802 unitPtr->max_hit_points / 200;
1803 if( damage >= unitPtr->hit_points)
1804 damage = unitPtr->hit_points -1;
1805 if( damage < (float) 5)
1806 damage = (float) 5;
1807
1808 unitPtr->hit_points -= damage;
1809 if( unitPtr->is_own() )
1810 unitDamage++;
1811
1812 if( unitPtr->hit_points <= 0)
1813 {
1814 unitPtr->hit_points = (float) 0;
1815 if( unitPtr->is_own() )
1816 unitDie++;
1817 }
1818 else
1819 {
1820 if( unit_res[unitPtr->unit_id]->solider_id &&
1821 weather.quake_rate(unitPtr->cur_x_loc(),unitPtr->cur_y_loc()) >= 60)
1822 {
1823 ((UnitVehicle *)unitPtr)->dismount();
1824 }
1825 }
1826 }
1827
1828 news_array.earthquake_damage(unitDamage-unitDie, unitDie, townDamage, firmDamage-firmDie, firmDie);
1829 }
1830 //-------- End of function World::earth_equake ------//
1831
1832
1833 //-------- Begin of function World::lightning_strike ------//
lightning_strike(short cx,short cy,short radius)1834 void World::lightning_strike(short cx, short cy, short radius)
1835 {
1836 short x, y;
1837 for( y = cy-radius; y <= cy+radius; ++y)
1838 {
1839 if( y < 0 || y >= max_y_loc)
1840 continue;
1841
1842 for( x = cx-radius; x <= cx+radius; ++x)
1843 {
1844 if( x < 0 || x >= max_x_loc)
1845 continue;
1846
1847 Location *locPtr = get_loc(x,y);
1848 if( locPtr->is_plant() )
1849 {
1850 // ---- add a fire on it ------//
1851 locPtr->set_fire_str(80);
1852 // ##### begin Gilbert 11/8 #####//
1853 if( locPtr->can_set_fire() && locPtr->fire_str() < 5 )
1854 locPtr->set_fire_str(5);
1855 // ##### end Gilbert 11/8 #####//
1856 }
1857 }
1858 }
1859
1860 // ------ check hitting units -------//
1861 int i;
1862 for( i=unit_array.size(); i > 0; i-- )
1863 {
1864 if( unit_array.is_deleted(i))
1865 continue;
1866
1867 Unit *unitPtr = unit_array[i];
1868
1869 // no damage to overseer
1870 if( !unitPtr->is_visible())
1871 continue;
1872
1873 if( unitPtr->cur_x_loc() <= cx+ radius &&
1874 unitPtr->cur_x_loc() + unitPtr->sprite_info->loc_width > cx-radius &&
1875 unitPtr->cur_y_loc() <= cy+radius &&
1876 unitPtr->cur_y_loc() + unitPtr->sprite_info->loc_height > cy-radius )
1877 {
1878 unitPtr->hit_points -= (float) unitPtr->sprite_info->lightning_damage / ATTACK_SLOW_DOWN;
1879
1880 // ---- add news -------//
1881 if( unitPtr->is_own() )
1882 news_array.lightning_damage(unitPtr->cur_x_loc(), unitPtr->cur_y_loc(),
1883 NEWS_LOC_UNIT, i, unitPtr->hit_points <= (float) 0);
1884
1885 if( unitPtr->hit_points <= 0)
1886 unitPtr->hit_points = (float) 0;
1887 }
1888 }
1889
1890 for( i=firm_array.size() ; i>0 ; i-- )
1891 {
1892 if( firm_array.is_deleted(i) || !firm_res[firm_array[i]->firm_id]->buildable)
1893 continue;
1894
1895 Firm *firmPtr = firm_array[i];
1896 if( firmPtr->loc_x1 <= cx+radius &&
1897 firmPtr->loc_x2 >= cx-radius &&
1898 firmPtr->loc_y1 <= cy+radius &&
1899 firmPtr->loc_y2 >= cy-radius)
1900 {
1901 firmPtr->hit_points -= (float) 50 / ATTACK_SLOW_DOWN;
1902
1903 // ---- add news -------//
1904 if( firmPtr->own_firm() )
1905 news_array.lightning_damage(firmPtr->center_x, firmPtr->center_y,
1906 NEWS_LOC_FIRM, i, firmPtr->hit_points <= (float) 0);
1907
1908 // ---- add a fire on it ------//
1909 Location *locPtr = get_loc(firmPtr->center_x, firmPtr->center_y);
1910 if( locPtr->can_set_fire() && locPtr->fire_str() < 5 )
1911 locPtr->set_fire_str(5);
1912
1913 if( firmPtr->hit_points <= 0)
1914 {
1915 firmPtr->hit_points = (float) 0;
1916 se_res.sound(firmPtr->center_x, firmPtr->center_y, 1,
1917 'F', firmPtr->firm_id, "DIE" );
1918 firm_array.del_firm(i);
1919 }
1920 }
1921 }
1922
1923 for( i=town_array.size() ; i>0 ; i-- )
1924 {
1925 if( town_array.is_deleted(i))
1926 continue;
1927
1928 Town *townPtr = town_array[i];
1929
1930 if( townPtr->loc_x1 <= cx+radius &&
1931 townPtr->loc_x2 >= cx-radius &&
1932 townPtr->loc_y1 <= cy+radius &&
1933 townPtr->loc_y2 >= cy-radius)
1934 {
1935 // ---- add news -------//
1936 if( townPtr->nation_recno == nation_array.player_recno )
1937 news_array.lightning_damage(townPtr->center_x, townPtr->center_y,
1938 NEWS_LOC_TOWN, i, 0);
1939
1940 // ---- add a fire on it ------//
1941 // ####### begin Gilbert 11/8 #########//
1942 Location *locPtr = get_loc(townPtr->center_x, townPtr->center_y);
1943 if( locPtr->can_set_fire() && locPtr->fire_str() < 5)
1944 locPtr->set_fire_str(5);
1945 // ####### end Gilbert 11/8 #########//
1946
1947 townPtr->kill_town_people(0);
1948 }
1949 }
1950 }
1951 //-------- End of function World::lightning_strike -------//
1952
1953
1954 // ------- Begin of function World::visit -----------//
1955 // set the visit_level surrounding unit, town and firm
visit(int xLoc1,int yLoc1,int xLoc2,int yLoc2,int range,int extend)1956 void World::visit(int xLoc1, int yLoc1, int xLoc2, int yLoc2, int range, int extend)
1957 {
1958 if(config.fog_of_war)
1959 {
1960 int left = MAX( 0, xLoc1 - range);
1961 int top = MAX( 0, yLoc1 - range);
1962 int right = MIN( MAX_WORLD_X_LOC-1, xLoc2 + range);
1963 int bottom = MIN( MAX_WORLD_Y_LOC-1, yLoc2 + range);
1964
1965 // ----- mark the visit_level of the square around the unit ------//
1966 for( int yLoc=top ; yLoc<=bottom ; yLoc++ )
1967 {
1968 Location *locPtr = get_loc(left, yLoc);
1969 for( int xLoc=left ; xLoc<=right ; xLoc++, locPtr++ )
1970 {
1971 locPtr->set_visited();
1972 }
1973 }
1974
1975 // ----- visit_level decreasing outside the visible range ------//
1976 if( extend > 0)
1977 {
1978 int visitLevel = FULL_VISIBILITY;
1979 int levelDrop = (FULL_VISIBILITY - EXPLORED_VISIBILITY) / (extend+1);
1980 xLoc1 -= range;
1981 xLoc2 += range;
1982 yLoc1 -= range;
1983 yLoc2 += range;
1984 for( ++range; extend > 0; --extend, ++range)
1985 {
1986 xLoc1--;
1987 xLoc2++;
1988 yLoc1--;
1989 yLoc2++;
1990 visitLevel -= levelDrop;
1991 visit_shell(xLoc1, yLoc1, xLoc2, yLoc2, visitLevel);
1992 }
1993 }
1994 }
1995 }
1996 // ------- End of function World::visit -----------//
1997
1998
1999 // ------- Begin of function World::visit_shell -----------//
2000 // set specific visit_level on the surrounding unit, town and firm
visit_shell(int xLoc1,int yLoc1,int xLoc2,int yLoc2,int visitLevel)2001 void World::visit_shell(int xLoc1, int yLoc1, int xLoc2, int yLoc2, int visitLevel)
2002 {
2003 int left = MAX( 0, xLoc1 );
2004 int top = MAX( 0, yLoc1 );
2005 int right = MIN( MAX_WORLD_X_LOC-1, xLoc2);
2006 int bottom = MIN( MAX_WORLD_Y_LOC-1, yLoc2);
2007
2008 // ------- top side ---------//
2009 if( yLoc1 >= 0)
2010 {
2011 Location *locPtr = get_loc( left, yLoc1);
2012 for( int x = left; x <= right; ++x, ++locPtr)
2013 locPtr->set_visited(visitLevel);
2014 }
2015
2016 // ------- bottom side ---------//
2017 if( yLoc2 < max_y_loc)
2018 {
2019 Location *locPtr = get_loc( left, yLoc2);
2020 for( int x = left; x <= right; ++x, ++locPtr)
2021 locPtr->set_visited(visitLevel);
2022 }
2023
2024 // ------- left side -----------//
2025 if( xLoc1 >= 0)
2026 {
2027 for( int y = top; y <= bottom; ++y)
2028 {
2029 get_loc(xLoc1,y)->set_visited(visitLevel);
2030 }
2031 }
2032
2033 // ------- right side -----------//
2034 if( xLoc2 < max_x_loc)
2035 {
2036 for( int y = top; y <= bottom; ++y)
2037 {
2038 get_loc(xLoc2,y)->set_visited(visitLevel);
2039 }
2040 }
2041
2042 }
2043 // ------- End of function World::visit_shell -----------//
2044
2045
2046 //------- Begin of function World::process_visibility -----------//
2047
process_visibility()2048 void World::process_visibility()
2049 {
2050 if( config.fog_of_war )
2051 {
2052 // ###### begin Gilbert 13/10 ########//
2053 #ifndef USE_ASM
2054 for( int y = 0; y < max_y_loc; ++y)
2055 {
2056 Location *locPtr = get_loc(0,y);
2057 for( int x = 0; x < max_x_loc; ++x, ++locPtr)
2058 {
2059 locPtr->dec_visibility();
2060 }
2061 }
2062 #else
2063 int count = max_x_loc * max_y_loc;
2064 const int sizeOfLoc = sizeof(Location);
2065 unsigned char *locVisitLevel = &get_loc(0,0)->visit_level;
2066 unsigned char decVisitLevel = EXPLORED_VISIBILITY*2+1;
2067 #ifdef _MSC_VER
2068 _asm
2069 {
2070 mov ecx, count
2071 mov ebx, locVisitLevel
2072 mov edx, sizeOfLoc
2073 mov ah, decVisitLevel
2074 process_visit_level_1:
2075 mov al,[ebx]
2076 cmp al,ah // if(al > EXPLORED_VISIBILITY*2) al--;
2077 cmc
2078 sbb al,0
2079 mov [ebx],al
2080 add ebx, edx
2081 loop process_visit_level_1
2082 }
2083 #else
2084 __asm__ __volatile__ (
2085 "movb %0, %%ah\n"
2086 "process_visit_level_1:\n\t"
2087 "movb (%%ebx), %%al\n\t"
2088 "cmpb %%ah, %%al\n\t"
2089 "cmc\n\t"
2090 "sbbb $0, %%al\n\t"
2091 "movb %%al, (%%ebx)\n\t"
2092 "addl %%edx, %%ebx\n\t"
2093 "loop process_visit_level_1\n\t"
2094 :
2095 : "m"(decVisitLevel), "b"(locVisitLevel), "c"(count), "d"(sizeOfLoc)
2096 : "%eax"
2097 );
2098 #endif
2099 #endif
2100 // ###### end Gilbert 13/10 ########//
2101 }
2102 }
2103 //------- End of function World::process_visibility -----------//
2104
2105
2106 //--------- Begin of function World::disp_next --------//
2107 //
2108 // Display the next object of the same type.
2109 //
2110 // <int> seekDir : -1 - display the previous one in the list.
2111 // 1 - display the next one in the list.
2112 //
2113 // <int> sameNation - whether display the next object of the same
2114 // nation only or of any nation.
2115 //
disp_next(int seekDir,int sameNation)2116 void World::disp_next(int seekDir, int sameNation)
2117 {
2118 //--- if the selected one is a unit ----//
2119
2120 if( unit_array.selected_recno )
2121 {
2122 unit_array.disp_next(seekDir, sameNation);
2123 }
2124
2125 //--- if the selected one is a firm ----//
2126
2127 if( firm_array.selected_recno )
2128 {
2129 firm_array.disp_next(seekDir, sameNation);
2130 }
2131
2132 //--- if the selected one is a town ----//
2133
2134 if( town_array.selected_recno )
2135 {
2136 town_array.disp_next(seekDir, sameNation);
2137 }
2138
2139 //--- if the selected one is a natural resource site ----//
2140
2141 if( site_array.selected_recno )
2142 {
2143 site_array.disp_next(seekDir, sameNation);
2144 }
2145 }
2146 //----------- End of function World::disp_next --------//
2147
2148 #ifdef DEBUG3
2149
2150 //--------- Begin of function World::get_loc --------//
2151 //
get_loc(int xLoc,int yLoc)2152 Location* World::get_loc(int xLoc, int yLoc)
2153 {
2154 err_when( xLoc<0 || xLoc>=MAX_WORLD_X_LOC );
2155 err_when( yLoc<0 || yLoc>=MAX_WORLD_Y_LOC );
2156
2157 return loc_matrix + MAX_WORLD_X_LOC * yLoc + xLoc;
2158 }
2159 //----------- End of function World::get_loc --------//
2160
2161
2162 //--------- Begin of function World::get_region_id --------//
2163 //
get_region_id(int xLoc,int yLoc)2164 uint8_t World::get_region_id(int xLoc, int yLoc)
2165 {
2166 err_when( xLoc<0 || xLoc>=MAX_WORLD_X_LOC );
2167 err_when( yLoc<0 || yLoc>=MAX_WORLD_Y_LOC );
2168
2169 return loc_matrix[MAX_WORLD_X_LOC*yLoc+xLoc].region_id;
2170 }
2171 //----------- End of function World::get_region_id --------//
2172
2173 #endif
2174
2175 // ####### begin Gilbert 25/7 #########//
2176 // return true if any location adjacent to (x,y) is on a particular region
is_adjacent_region(int x,int y,int regionId)2177 int World::is_adjacent_region(int x, int y, int regionId)
2178 {
2179 if( y > 0 )
2180 {
2181 if( x > 0 )
2182 {
2183 if( get_region_id(x-1,y-1) == regionId )
2184 return 1;
2185 }
2186 if( get_region_id(x,y-1) == regionId )
2187 return 1;
2188 if( x < max_x_loc-1 )
2189 {
2190 if( get_region_id(x+1,y-1) == regionId )
2191 return 1;
2192 }
2193 }
2194 if( x > 0 )
2195 {
2196 if( get_region_id(x-1,y) == regionId )
2197 return 1;
2198 }
2199 if( x < max_x_loc-1 )
2200 {
2201 if( get_region_id(x+1,y) == regionId )
2202 return 1;
2203 }
2204 if( y < max_y_loc-1)
2205 {
2206 if( x > 0 )
2207 {
2208 if( get_region_id(x-1,y+1) == regionId )
2209 return 1;
2210 }
2211 if( get_region_id(x,y+1) == regionId )
2212 return 1;
2213 if( x < max_x_loc-1 )
2214 {
2215 if( get_region_id(x+1,y+1) == regionId )
2216 return 1;
2217 }
2218 }
2219 return 0;
2220 }
2221 // ####### end Gilbert 25/7 #########//
2222