/* * Seven Kingdoms: Ancient Adversaries * * Copyright 1997,1998 Enlight Software Ltd. * * This program is free software: you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by * the Free Software Foundation, either version 2 of the License, or * (at your option) any later version. * * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * * You should have received a copy of the GNU General Public License * along with this program. If not, see . * */ //Filename : OWORLD.CPP //Description : Object World #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include //------------ Define static class variables ------------// short World::view_top_x, World::view_top_y; int World::max_x_loc=200, World::max_y_loc=200; //----------- Begin of function World::World ----------// World::World() { memset( this, 0, sizeof(World) ); //------- initialize matrix objects -------// map_matrix = new MapMatrix; zoom_matrix = new ZoomMatrix; } //------------- End of function World::World -----------// //----------- Begin of function World::~World ----------// World::~World() { if( map_matrix ) { delete map_matrix; map_matrix = NULL; } if( zoom_matrix ) { delete zoom_matrix; zoom_matrix = NULL; } deinit(); } //------------- End of function World::~World -----------// //----------- Begin of function World::init ----------// void World::init() { //----------- initialize vars -------------// scan_fire_x = 0; scan_fire_y = 0; lightning_signal = 0; map_matrix->init_para(); zoom_matrix->init_para(); } //------------- End of function World::init -----------// //----------- Begin of function World::deinit ----------// void World::deinit() { if( loc_matrix ) { mem_del( loc_matrix ); loc_matrix = NULL; } } //------------- End of function World::deinit -----------// //--------- Begin of function World::assign_map ----------// // // After a map is loaded, assign_map() need to be called to // initial map_matrix and zoom_matrix // void World::assign_map() { //------------- assign map -------------// map_matrix-> assign_map(loc_matrix, max_x_loc, max_y_loc ); zoom_matrix->assign_map(loc_matrix, max_x_loc, max_y_loc ); //-------- set the zoom area box on map matrix ------// map_matrix->cur_x_loc = 0; map_matrix->cur_y_loc = 0; map_matrix->cur_cargo_width = zoom_matrix->disp_x_loc; map_matrix->cur_cargo_height = zoom_matrix->disp_y_loc; } //----------- End of function World::assign_map ----------// //----------- Begin of function World::paint ------------// // // Paint world window and scroll bars // void World::paint() { map_matrix->paint(); zoom_matrix->paint(); } //----------- End of function World::paint ------------// //----------- Begin of function World::refresh ------------// // void World::refresh() { map_matrix->refresh(); zoom_matrix->refresh(); } //----------- End of function World::refresh ------------// //----------- Begin of function World::process ------------// // // Called every frame // void World::process() { //-------- process wall ----------// form_world_wall(); //-------- process fire -----------// // BUGHERE : set Location::flammability for every change in cargo world.spread_fire(weather); // ------- process visibility --------// process_visibility(); //-------- process lightning ------// // ###### begin Gilbert 11/8 ########// if(lightning_signal== 0 && weather.is_lightning()) { // ------- create new lightning ----------// lightning_signal = 110; } if( lightning_signal == 106 && config.weather_effect) { lightning_strike(m.random(MAX_MAP_WIDTH), m.random(MAX_MAP_HEIGHT), 1); } if(lightning_signal == 100) lightning_signal = 5 + m.random(10); else if( lightning_signal) lightning_signal--; // ###### end Gilbert 11/8 ########// //---------- process ambient sound ---------// if( sys.frame_count%10 == 0 ) // process once per ten frames process_ambient_sound(); // --------- update scan fire x y ----------// if(++scan_fire_x >= SCAN_FIRE_DIST) { scan_fire_x = 0; if( ++scan_fire_y >= SCAN_FIRE_DIST) scan_fire_y =0; } } //----------- End of function World::process ------------// //----------- Begin of function World::next_day ------------// // // Called every frame // void World::next_day() { plant_ops(); weather = weather_forecast[0]; for(int foreDay=0; foreDay < MAX_WEATHER_FORECAST-1; ++foreDay) { weather_forecast[foreDay] = weather_forecast[foreDay+1]; } weather_forecast[MAX_WEATHER_FORECAST-1].next_day(); // ####### begin Gilbert 11/7 #########// magic_weather.next_day(); // ####### end Gilbert 11/7 #########// if(weather.has_tornado() && config.weather_effect) { tornado_array.add_tornado(weather.tornado_x_loc(max_x_loc, max_y_loc), weather.tornado_y_loc(max_x_loc, max_y_loc), 600); } // ######## begin Gilbert 31/7 #######// if( weather.is_quake() && config.random_event_frequency) // ######## end Gilbert 31/7 #######// { earth_quake(); } //-------- Debug code: BUGHERE ----------// #ifdef DEBUG Location* locPtr = loc_matrix; for( int y=0 ; yhas_unit(UNIT_LAND) ) { err_when( unit_array.is_truly_deleted( locPtr->unit_recno(UNIT_LAND) ) ); } locPtr++; } } #endif } //----------- End of function World::next_day ------------// //----------- Begin of function World::detect ------------// // // Detect mouse action from user // // Return : 1 - mouse pressed on World area // 0 - mouse not pressed on World area // int World::detect() { if( map_matrix->detect() ) return 1; if( zoom_matrix->detect() ) return 1; if( detect_scroll() ) return 1; // ##### begin Gilbert 16/9 #######// // return detect_firm_town(); return 0; // ##### end Gilbert 16/9 #######// } //----------- End of function World::detect ------------// //--------- Begin of function World::detect_scroll ---------// // // Detect if the mouse cursor is pushed towards the border // of the screen to scroll the zoom window. // int World::detect_scroll() { if( mouse_cursor.frame_flag ) // if it's now in frame selection mode return 0; if( next_scroll_time && m.get_time() < next_scroll_time ) // just scrolled not too long ago, wait for a little while before next scroll. return 0; int rc=0; //----- scroll left -----// if( mouse.cur_x == mouse.bound_x1 ) { zoom_matrix->scroll(-1,0); rc = 1; } //---- scroll right -----// if( mouse.cur_x == mouse.bound_x2 ) { zoom_matrix->scroll(1,0); rc = 1; } //---- scroll top -------// if( mouse.cur_y == mouse.bound_y1 ) { zoom_matrix->scroll(0,-1); rc = 1; } //---- scroll bottom ----// if( mouse.cur_y == mouse.bound_y2 ) { zoom_matrix->scroll(0,1); rc = 1; } //----- set next scroll time based on scroll_speed -----// // // slowest scroll speed: 500/1 = 500 milliseconds or 1/2 second // fastest scroll speed: 500/10 = 50 milliseconds or 1/20 second // //------------------------------------------------------// if( rc ) { sys.zoom_need_redraw = 1; // ask the zoom window to refresh next time next_scroll_time = m.get_time() + 500/(config.scroll_speed+1); } return rc; } //----------- End of function World::detect_scroll -----------// //--------- Begin of function World::go_loc --------// // // Go to a specified location. // // xLoc, yLoc - location to go to. // [int] selectFlag - whether should the object on the location if // there is one. (default: 0) // void World::go_loc(int xLoc, int yLoc, int selectFlag) { //------- set location ---------// zoom_matrix->cur_x_loc = xLoc; zoom_matrix->cur_y_loc = yLoc; map_matrix->cur_x_loc = xLoc - zoom_matrix->disp_x_loc/2; map_matrix->cur_y_loc = yLoc - zoom_matrix->disp_y_loc/2; //--------- refresh ------------// map_matrix->valid_cur_box(); zoom_matrix->top_x_loc = map_matrix->cur_x_loc; zoom_matrix->top_y_loc = map_matrix->cur_y_loc; sys.zoom_need_redraw = 1; //---- if should select the object on the location ----// if( selectFlag ) { Location* locPtr = world.get_loc(xLoc, yLoc); if( locPtr->has_any_unit() ) { int mobileType; int unitRecno = locPtr->get_any_unit( mobileType ); power.reset_selection(); unit_array[unitRecno]->selected_flag = 1; unit_array.selected_recno = unitRecno; unit_array.selected_count++; } else if( locPtr->is_firm() ) { power.reset_selection(); firm_array.selected_recno = locPtr->firm_recno(); } else if( locPtr->is_town() ) { power.reset_selection(); town_array.selected_recno = locPtr->town_recno(); } else if( locPtr->has_site() ) { power.reset_selection(); site_array.selected_recno = locPtr->site_recno(); } } //------- refresh the display -------// info.disp(); } //----------- End of function World::go_loc --------// //-------- Begin of function World::unveil ---------// // // Unveil all surrounding areas of the given object. // // xLoc1, yLoc1 = the position of the object. // xLoc2, yLoc2 = the position of the object. // void World::unveil(int xLoc1, int yLoc1, int xLoc2, int yLoc2) { if( config.explore_whole_map ) return; xLoc1 = max( 0, xLoc1 - EXPLORE_RANGE); yLoc1 = max( 0, yLoc1 - EXPLORE_RANGE); xLoc2 = min( MAX_WORLD_X_LOC-1, xLoc2 + EXPLORE_RANGE); yLoc2 = min( MAX_WORLD_Y_LOC-1, yLoc2 + EXPLORE_RANGE); explore( xLoc1, yLoc1, xLoc2, yLoc2 ); } //--------- End of function World::unveil ---------// //-------- Begin of function World::explore ---------// // // Explore a specific area. No further exploration around the area. // // xLoc1, yLoc1 = the position of the area. // xLoc2, yLoc2 = the position of the area. // void World::explore(int xLoc1, int yLoc1, int xLoc2, int yLoc2) { if( config.explore_whole_map ) return; int xLoc, yLoc; Location* locPtr; char* imageBuf = map_matrix->save_image_buf + sizeof(short)*2; char* nationColorArray = nation_array.nation_power_color_array; char* writePtr; int shadowMapDist = max_x_loc + 1; int tileYOffset; Location *northWestPtr; char tilePixel; for( yLoc=yLoc1 ; yLoc<=yLoc2 ; yLoc++ ) { locPtr = get_loc(xLoc1, yLoc); for( xLoc=xLoc1 ; xLoc<=xLoc2 ; xLoc++, locPtr++ ) { if( !locPtr->explored() ) { locPtr->explored_on(); //-------- draw pixel ----------// writePtr = imageBuf+MAP_WIDTH*yLoc+xLoc; switch( world.map_matrix->map_mode ) { case MAP_MODE_TERRAIN: if( locPtr->fire_str() > 0) *writePtr = (char) FIRE_COLOR; else if( locPtr->is_plant() ) *writePtr = plant_res.plant_map_color; else { tileYOffset = (yLoc & TERRAIN_TILE_Y_MASK) * TERRAIN_TILE_WIDTH; tilePixel = terrain_res.get_map_tile(locPtr->terrain_id)[tileYOffset + (xLoc & TERRAIN_TILE_X_MASK)]; if( xLoc == 0 || yLoc == 0) { *writePtr = tilePixel; } else { northWestPtr = locPtr - shadowMapDist; if( (terrain_res[locPtr->terrain_id]->average_type >= terrain_res[northWestPtr->terrain_id]->average_type) ) { *writePtr = tilePixel; } else { *writePtr = (char) VGA_GRAY; } } break; } break; case MAP_MODE_SPOT: if( locPtr->sailable() ) *writePtr = (char) 0x32; else if( locPtr->has_hill() ) *writePtr = (char) V_BROWN; else if( locPtr->is_plant() ) *writePtr = (char) V_DARK_GREEN; else *writePtr = (char) VGA_GRAY+10; break; case MAP_MODE_POWER: if( locPtr->sailable() ) *writePtr = (char) 0x32; else if( locPtr->has_hill() ) *writePtr = (char) V_BROWN; else if( locPtr->is_plant() ) *writePtr = (char) V_DARK_GREEN; else *writePtr = nationColorArray[locPtr->power_nation_recno]; break; } //---- if the command base of the opponent revealed, establish contact ----// if( locPtr->is_firm() ) { Firm* firmPtr = firm_array[locPtr->firm_recno()]; if( firmPtr->nation_recno > 0 && nation_array.player_recno ) { NationRelation *relation = (~nation_array)->get_relation(firmPtr->nation_recno); if( !relation->has_contact ) { if( !remote.is_enable() ) { (~nation_array)->establish_contact(firmPtr->nation_recno); } else { if( !relation->contact_msg_flag ) { // packet structure : short *shortPtr = (short *)remote.new_send_queue_msg(MSG_NATION_CONTACT, 2*sizeof(short)); *shortPtr = nation_array.player_recno; shortPtr[1] = firmPtr->nation_recno; relation->contact_msg_flag = 1; } } } } } if( locPtr->is_town() ) { Town* townPtr = town_array[locPtr->town_recno()]; if( townPtr->nation_recno > 0 && nation_array.player_recno ) { NationRelation *relation = (~nation_array)->get_relation(townPtr->nation_recno); if( !relation->has_contact ) { if( !remote.is_enable() ) { (~nation_array)->establish_contact(townPtr->nation_recno); } else { if( !relation->contact_msg_flag ) { // packet structure : short *shortPtr = (short *)remote.new_send_queue_msg(MSG_NATION_CONTACT, 2*sizeof(short)); *shortPtr = nation_array.player_recno; shortPtr[1] = townPtr->nation_recno; relation->contact_msg_flag = 1; } } } } } } } } } //--------- End of function World::explore ---------// //-------- Begin of function World::is_explored ---------// // // Check if the whole area has been explored or not. // // xLoc1, yLoc1 = the coordination of the area to explore // xLoc2, yLoc2 = the coordination of the area to explore // int World::is_explored(int xLoc1, int yLoc1, int xLoc2, int yLoc2) { if( config.explore_whole_map ) return 1; int xLoc, yLoc; Location* locPtr; for( yLoc=yLoc1 ; yLoc<=yLoc2 ; yLoc++ ) { locPtr = get_loc(xLoc1, yLoc); for( xLoc=xLoc1 ; xLoc<=xLoc2 ; xLoc++, locPtr++ ) { if( !locPtr->explored() ) return 0; } } return 1; } //--------- End of function World::is_explored ---------// //----------- Begin of function World::load_map ------------// // // Load a custom map file. // void World::load_map(char* fileName) { generate_map(); return; //---------- initialize the map matrix --------// max_x_loc = 200; max_y_loc = 200; loc_matrix = (Location*) mem_resize( loc_matrix , max_x_loc * max_y_loc * sizeof(Location) ); memset( loc_matrix, 0, sizeof(Location) * max_x_loc * max_y_loc ); int baseType = TERRAIN_DARK_DIRT; int terrainId = terrain_res.scan(baseType, MIDDLE_MASK, baseType, MIDDLE_MASK, baseType, MIDDLE_MASK, baseType, MIDDLE_MASK, 1); // 1-get the first instance for( int i=0 ; i xLoc1 = the upper left x // yLoc1 = the upper left y // xLoc2 = the lower right x // yLoc2 = the lower right y // [int] mobileType = mobile type (default: UNIT_LAND) // [int] buildFlag = whether the located area is for building a firm/town // if so, the location must no have any raw site. // (default: 0) // // return 1 for true. 0 for false // inline int World::check_unit_space(int xLoc1, int yLoc1, int xLoc2, int yLoc2, int mobileType, int buildFlag) { if(xLoc1<0 || xLoc1>=MAX_WORLD_X_LOC) return 0; if(yLoc1<0 || yLoc1>=MAX_WORLD_Y_LOC) return 0; if(xLoc2<0 || xLoc2>=MAX_WORLD_X_LOC) return 0; if(yLoc2<0 || yLoc2>=MAX_WORLD_Y_LOC) return 0; Location* locPtr = world.get_loc(xLoc1, yLoc1); int x, y; int canBuildFlag = 1; for(y=yLoc1; y<=yLoc2; y++) { locPtr = world.get_loc(xLoc1, y); for(x=xLoc1; x<=xLoc2; x++, locPtr++) { if( !locPtr->can_move(mobileType) || ( buildFlag && (locPtr->is_power_off() || locPtr->has_site()) ) ) // if build a firm/town, there must not be any sites in the area { canBuildFlag=0; break; } } if(canBuildFlag==0) break; } if( canBuildFlag ) return 1; else return 0; } //-------- End of function World::check_unit_space ------// //-------- Begin of function World::locate_space ------// // // Locate an area in the world map around the firm to place // the unit // // xLoc1 = the upper left x location of the building, also for returning the result location // yLoc1 = the upper left y location of the building // xLoc2 = the lower right x location of the building // yLoc2 = the lower right y location of the building // spaceLocWidth = the location width of the required space // spaceLocHeight = the location height of the required space // [int] mobileType = mobile type (default: UNIT_LAND) // [int] regionId = specify the region no. of the location to locate // (default: region no. of xLoc1, yLoc1) // [int] buildFlag = whether the located area is for building a firm/town // if so, the location must no have any raw site. // (default: 0) // // return : 1 - free space found // 0 - free space not found // int World::locate_space(int& xLoc1, int& yLoc1, int xLoc2, int yLoc2, int spaceLocWidth, int spaceLocHeight, int mobileType, int regionId, int buildFlag) { if( !regionId ) regionId = get_loc(xLoc1, yLoc1)->region_id; int isPlateau = get_loc(xLoc1, yLoc1)->is_plateau(); //-----------------------------------------------------------// // xLoc, yLoc is the adjusted upper left corner location of // the firm. with the adjustment, it is easier to do the following // checking. //-----------------------------------------------------------// Location* locPtr; int xLoc = xLoc1 - spaceLocWidth + 1; int yLoc = yLoc1 - spaceLocHeight + 1; if(xLoc < 0) xLoc = 0; if(yLoc < 0) yLoc = 0; int width = xLoc2 - xLoc + 1; int height = yLoc2 - yLoc + 1; int loopCount=0; while(1) { err_when( ++loopCount > MAX_WORLD_X_LOC * MAX_WORLD_Y_LOC * 4 ); //-----------------------------------------------------------// // step 1 //-----------------------------------------------------------// int xOffset = width/2; int yOffset = height; int x, y; x = xLoc + xOffset; y = yLoc + yOffset; if(x>=0 && y>=0 && x+spaceLocWidth-1region_id == regionId && locPtr->is_plateau() == isPlateau && check_unit_space(x, y, x+spaceLocWidth-1, y+spaceLocHeight-1, mobileType, buildFlag)) { xLoc1 = x; yLoc1 = y; return 1; } } } int sign = -1; int i, j, k, limit; //-----------------------------------------------------------// // step 2 //-----------------------------------------------------------// //y = yLoc + yOffset; limit = width + 2; for(i=1; i=0 && y>=0 && x+spaceLocWidth-1region_id == regionId && locPtr->is_plateau() == isPlateau && check_unit_space(x, y, x+spaceLocWidth-1, y+spaceLocHeight-1, mobileType, buildFlag)) { xLoc1 = x; yLoc1 = y; return 1; } } } sign *= -1; } //-----------------------------------------------------------// // step 3 //-----------------------------------------------------------// i = limit-1; limit = (height+1)*2; int r = sign*i; int lastX = xOffset; //int lastY = yOffset; for(j=0; j=0 && y>=0 && x+spaceLocWidth-1region_id == regionId && locPtr->is_plateau() == isPlateau && check_unit_space(x, y, x+spaceLocWidth-1, y+spaceLocHeight-1, mobileType, buildFlag)) { xLoc1 = x; yLoc1 = y; return 1; } } } } else { xOffset = lastX + r; yOffset--; x = xLoc + xOffset; y = yLoc + yOffset; if(x>=0 && y>=0 && x+spaceLocWidth-1region_id == regionId && locPtr->is_plateau() == isPlateau && check_unit_space(x, y, x+spaceLocWidth-1, y+spaceLocHeight-1, mobileType, buildFlag)) { xLoc1 = x; yLoc1 = y; return 1; } } } } } //-----------------------------------------------------------// // step 4 //-----------------------------------------------------------// y = yLoc + yOffset; for(k=0; k<=width; k++) { sign *= -1; i--; r = sign*i; xOffset -= r; x = xLoc + xOffset; if(x>=0 && y>=0 && x+spaceLocWidth-1region_id == regionId && locPtr->is_plateau() == isPlateau && check_unit_space(x, y, x+spaceLocWidth-1, y+spaceLocHeight-1, mobileType, buildFlag)) { xLoc1 = x; yLoc1 = y; return 1; } } } } //-----------------------------------------------------------// // re-init the parameters //-----------------------------------------------------------// if(xLoc<=0 && yLoc<=0 && width>=MAX_WORLD_X_LOC && height>=MAX_WORLD_Y_LOC) break; // the whole map has been checked width += 2; height += 2; xLoc -= 1; yLoc -= 1; if(xLoc<0) { xLoc = 0; width--; } if(yLoc<0) { yLoc=0; height--; } if(xLoc+width>MAX_WORLD_X_LOC) width--; if(yLoc+height>MAX_WORLD_Y_LOC) height--; //if(width==xLoc2-xLoc1+spaceLocWidth && height==yLoc2-yLoc1+spaceLocHeight) // terminate the checking // return 0; } return 0; } //-------- End of function World::locate_space ------// //-------- Begin of function World::locate_space_random ------// // // Locate an area of space in the world map randomly. Pick any // space available in that area without a specific scanning order. // // xLoc1 = the scaning range, also for returning the result location // yLoc1 = the scaning range // xLoc2 = the scaning range // yLoc2 = the scaning range // spaceLocWidth = the location width of the required space // spaceLocHeight = the location height of the required space // maxTries = maximum no. of tries // [int] regionId = if this is specified, the result location will // be in this region. // [int] buildSite = whether locating space for building a site // (default: 0) // [char] teraMask = terrain mask (default: 1) // // return : 1 - free space found // 0 - free space found // int World::locate_space_random(int& xLoc1, int& yLoc1, int xLoc2, int yLoc2, int spaceLocWidth, int spaceLocHeight, int maxTries, int regionId, int buildSite, char teraMask) { int i, x, y, xTemp, xLoc, yLoc, canBuildFlag; int scanWidth = xLoc2-xLoc1-spaceLocWidth+2; //xLoc2-xLoc1+1-spaceLocWidth+1; int scanHeight = yLoc2-yLoc1-spaceLocHeight+2; //yLoc2-yLoc1+1-spaceLocHeight+1; Location* locPtr; for( i=0 ; i=yLoc; y-- ) { locPtr = world.get_loc(xTemp, y); for(x=xTemp; x>=xLoc; x--, locPtr-- ) { if( ( buildSite ? !locPtr->can_build_site(teraMask) : !locPtr->can_build_firm(teraMask) ) || locPtr->is_power_off() ) { canBuildFlag=0; break; } } if(!canBuildFlag) break; } if( !canBuildFlag ) continue; //------ check region id. ------------// locPtr = world.get_loc(xLoc, yLoc); if( regionId && locPtr->region_id != regionId ) continue; //------------------------------------// xLoc1 = xLoc; yLoc1 = yLoc; err_when(buildSite && !locPtr->can_build_site(teraMask));//-*** hard codes for mine size 3x3 return 1; } return 0; } //-------- End of function World::locate_space_random ------// //-------- Begin of function World::can_build_firm ---------// // // Check if it is free to construct a building on the specific area. // // xLoc1, yLoc1 = the coordination of the area to can_build // firmId = id. of the firm // [short] unitRecno = the unit recno of the unit to build the firm // if the builder unit stands on the building area, still consider the area as buildable // (default: -1, do not take the builder into account) // int World::can_build_firm(int xLoc1, int yLoc1, int firmId, short unitRecno) { if( xLoc1 < 0 || yLoc1 < 0 || xLoc1 > MAX_WORLD_X_LOC || yLoc1 > MAX_WORLD_Y_LOC ) return 0; //------------------------------------------// FirmInfo* firmInfo = firm_res[firmId]; int xLoc, yLoc; int xLoc2 = xLoc1 + firmInfo->loc_width - 1; int yLoc2 = yLoc1 + firmInfo->loc_height - 1; if(xLoc2>=max_x_loc || yLoc2>max_y_loc) return 0; Location* locPtr; char teraMask, pierFlag; switch(firmInfo->tera_type) { case 1: // default : land firm case 2: // sea firm case 3: // land or sea firm teraMask = firmInfo->tera_type; for( yLoc=yLoc1 ; yLoc<=yLoc2 ; yLoc++ ) { locPtr = get_loc(xLoc1, yLoc); for( xLoc=xLoc1 ; xLoc<=xLoc2 ; xLoc++, locPtr++ ) { // ##### patch begin Gilbert 14/3 ######// if(!locPtr->can_build_firm(teraMask) && (!locPtr->has_unit(UNIT_LAND) || locPtr->unit_recno(UNIT_LAND)!=unitRecno)) return 0; // ##### patch end Gilbert 14/3 ######// if( firmId != FIRM_MINE && locPtr->has_site() ) // don't allow building any buildings other than mines on a location with a site return 0; } } return 1; case 4: // special firm, such as harbor // must be 3x3, // centre square of one side is land (teraMask=1), // two squares on that side can be land or sea (teraMask=3) // and other (6 squares) are sea (teraMask=2) if( firmInfo->loc_width != 3 || firmInfo->loc_height != 3) return 0; pierFlag = 1|2|4|8; // bit0=north, bit1=south, bit2=west, bit3=east for( yLoc=yLoc1 ; yLoc<=yLoc2 ; yLoc++ ) { locPtr = get_loc(xLoc1, yLoc); for( xLoc=xLoc1 ; xLoc<=xLoc2 ; xLoc++, locPtr++ ) { if( locPtr->has_site() ) // don't allow building any buildings other than mines on a location with a site return 0; static char northPierTera[3][3] = { {2,2,2},{2,2,2},{3,1,3} }; static char southPierTera[3][3] = { {3,1,3},{2,2,2},{2,2,2} }; static char westPierTera[3][3] = { {2,2,3},{2,2,1},{2,2,3} }; static char eastPierTera[3][3] = { {3,2,2},{1,2,2},{3,2,2} }; int x = xLoc - xLoc1; int y = yLoc - yLoc1; if(!locPtr->can_build_harbor(northPierTera[y][x]) ) pierFlag &= ~1; if(!locPtr->can_build_harbor(southPierTera[y][x]) ) pierFlag &= ~2; if(!locPtr->can_build_harbor(westPierTera[y][x]) ) pierFlag &= ~4; if(!locPtr->can_build_harbor(eastPierTera[y][x]) ) pierFlag &= ~8; } } err_when( pierFlag != 0 && pierFlag != 1 && pierFlag != 2 && pierFlag != 4 && pierFlag != 8 ); return pierFlag; break; // other tera_type here default: err_here(); return 0; } } //--------- End of function World::can_build_firm ---------// //-------- Begin of function World::can_build_town ---------// // // xLoc1, yLoc1 = the coordination of the area to can_build // [short] unitRecno = the unit recno of the unit to build the town // if the builder unit stands on the building area, still consider the area as buildable // (default: -1, do not take the builder into account) // int World::can_build_town(int xLoc1, int yLoc1, short unitRecno) { int xLoc, yLoc; int xLoc2 = xLoc1 + STD_TOWN_LOC_WIDTH - 1; int yLoc2 = yLoc1 + STD_TOWN_LOC_HEIGHT - 1; if(xLoc2>=max_x_loc || yLoc2>=max_y_loc) return 0; Location* locPtr; for( yLoc=yLoc1 ; yLoc<=yLoc2 ; yLoc++ ) { locPtr = get_loc(xLoc1, yLoc); for( xLoc=xLoc1 ; xLoc<=xLoc2 ; xLoc++, locPtr++ ) { // ##### patch begin Gilbert 14/3 ######// // allow the building unit to stand in the area if( !locPtr->can_build_town() && (!locPtr->has_unit(UNIT_LAND) || locPtr->unit_recno(UNIT_LAND)!=unitRecno) ) return 0; // ##### patch end Gilbert 14/3 ######// } } return 1; } //--------- End of function World::can_build_town ---------// //-------- Begin of function World::can_build_wall ---------// // // xLoc, yLoc = the coordination of the area to can_build // nationRecno = recno of the builder nation. // int World::can_build_wall(int xLoc, int yLoc, short nationRecno) { Location* locPtr = get_loc(xLoc, yLoc); return locPtr->can_build_wall() && locPtr->power_nation_recno == nationRecno; } //--------- End of function World::can_build_wall ---------// //-------- Begin of function World::can_destruct_wall ---------// // // xLoc, yLoc = the coordination of the area to can_build // nationRecno = recno of the builder nation. // int World::can_destruct_wall(int xLoc, int yLoc, short nationRecno) { Location* locPtr = get_loc(xLoc, yLoc); return locPtr->is_wall() && locPtr->power_nation_recno == nationRecno; } //--------- End of function World::can_destruct_wall ---------// //---------- Begin of function World::draw_link_line -----------// // // srcFirmId - id. of the source firm. // 0 if the source is a town // srcTownRecno - town recno of the source town // 0 if the source is a firm // srcXLoc1, srcYLoc1 - the location of the source area // srcXLoc2, srcYLoc2 // // [int] giveEffectiveDis - use this value as the effective distance if this is given // (default: 0) // void World::draw_link_line(int srcFirmId, int srcTownRecno, int srcXLoc1, int srcYLoc1, int srcXLoc2, int srcYLoc2, int givenEffectiveDis) { if( srcFirmId == FIRM_INN ) // FirmInn's link is only for scan for neighbor inns quickly, the link line is not displayed return; //--------------------------------------// int srcXLoc = (srcXLoc1 + srcXLoc2)/2; int srcYLoc = (srcYLoc1 + srcYLoc2)/2; int srcX = ( ZOOM_X1 + (srcXLoc1-zoom_matrix->top_x_loc) * ZOOM_LOC_WIDTH + ZOOM_X1 + (srcXLoc2-zoom_matrix->top_x_loc+1) * ZOOM_LOC_WIDTH ) / 2; int srcY = ( ZOOM_Y1 + (srcYLoc1-zoom_matrix->top_y_loc) * ZOOM_LOC_HEIGHT + ZOOM_Y1 + (srcYLoc2-zoom_matrix->top_y_loc+1) * ZOOM_LOC_HEIGHT ) / 2; //------- draw lines connected to town ---------// int i, townX, townY, effectiveDis; Town* townPtr; if( givenEffectiveDis ) effectiveDis = givenEffectiveDis; else { if( srcFirmId ) effectiveDis = EFFECTIVE_FIRM_TOWN_DISTANCE; else effectiveDis = EFFECTIVE_TOWN_TOWN_DISTANCE; } if( !srcFirmId || firm_res[srcFirmId]->is_linkable_to_town ) // don't draw link line to town if it's an inn { for( i=town_array.size() ; i>0 ; i-- ) { if( town_array.is_deleted(i) ) continue; townPtr = town_array[i]; if( srcTownRecno && townPtr->town_recno != srcTownRecno ) continue; //-------- check the distance --------// if( m.points_distance( townPtr->center_x, townPtr->center_y, srcXLoc, srcYLoc ) > effectiveDis ) { continue; } //------ check if both are on the same terrain type ------// if( (world.get_loc(townPtr->center_x, townPtr->center_y)->is_plateau()==1) != (world.get_loc(srcXLoc, srcYLoc)->is_plateau()==1) ) { continue; } //---------- draw line now -----------// townX = ( ZOOM_X1 + (townPtr->loc_x1-zoom_matrix->top_x_loc) * ZOOM_LOC_WIDTH + ZOOM_X1 + (townPtr->loc_x2-zoom_matrix->top_x_loc+1) * ZOOM_LOC_WIDTH ) / 2; townY = ( ZOOM_Y1 + (townPtr->loc_y1-zoom_matrix->top_y_loc) * ZOOM_LOC_HEIGHT + ZOOM_Y1 + (townPtr->loc_y2-zoom_matrix->top_y_loc+1) * ZOOM_LOC_HEIGHT ) / 2; anim_line.draw_line(&vga_back, srcX, srcY, townX, townY); } } //------- draw lines connected to firms ---------// if( givenEffectiveDis ) effectiveDis = givenEffectiveDis; else { if( srcFirmId ) effectiveDis = EFFECTIVE_FIRM_FIRM_DISTANCE; else effectiveDis = EFFECTIVE_FIRM_TOWN_DISTANCE; } int firmX, firmY, linkFlag; Firm* firmPtr; for( i=firm_array.size() ; i>0 ; i-- ) { if( firm_array.is_deleted(i) ) continue; firmPtr = firm_array[i]; //------ only link if the firms have relationship -----// if( srcFirmId ) linkFlag = firm_res[firmPtr->firm_id]->is_linkable_to_firm(srcFirmId); else linkFlag = firm_res[firmPtr->firm_id]->is_linkable_to_town; if( !linkFlag ) continue; //-------- check the distance --------// if( m.points_distance( firmPtr->center_x, firmPtr->center_y, srcXLoc, srcYLoc ) > effectiveDis ) { continue; } //------ check if both are on the same terrain type ------// if( (world.get_loc(firmPtr->center_x, firmPtr->center_y)->is_plateau()==1) != (world.get_loc(srcXLoc, srcYLoc)->is_plateau()==1) ) { continue; } //---------- draw line now -----------// firmX = ( ZOOM_X1 + (firmPtr->loc_x1-zoom_matrix->top_x_loc) * ZOOM_LOC_WIDTH + ZOOM_X1 + (firmPtr->loc_x2-zoom_matrix->top_x_loc+1) * ZOOM_LOC_WIDTH ) / 2; firmY = ( ZOOM_Y1 + (firmPtr->loc_y1-zoom_matrix->top_y_loc) * ZOOM_LOC_HEIGHT + ZOOM_Y1 + (firmPtr->loc_y2-zoom_matrix->top_y_loc+1) * ZOOM_LOC_HEIGHT ) / 2; anim_line.draw_line(&vga_back, srcX, srcY, firmX, firmY); } } //----------- End of function World::draw_link_line ------------// //-------- Begin of function World::set_surr_power_off ---------// void World::set_surr_power_off(int xLoc, int yLoc) { if(xLoc>0) // west get_loc(xLoc-1, yLoc)->set_power_off(); if(xLocset_power_off(); if(yLoc>0) // north get_loc(xLoc, yLoc-1)->set_power_off(); if(yLocset_power_off(); } //----------- End of function World::set_surr_power_off ------------// //-------- Begin of function World::set_all_power ---------// // void World::set_all_power() { //--------- set town's influence -----------// Town* townPtr; int i; for( i=town_array.size() ; i>0 ; i-- ) { if( town_array.is_deleted(i) ) continue; townPtr = town_array[i]; if( !townPtr->nation_recno ) continue; //------- set the influence range of this town -----// set_power(townPtr->loc_x1, townPtr->loc_y1, townPtr->loc_x2, townPtr->loc_y2, (char)townPtr->nation_recno); } //--------- set firm's influence -----------// Firm* firmPtr; for( i=firm_array.size() ; i>0 ; i-- ) { if( firm_array.is_deleted(i) ) continue; firmPtr = firm_array[i]; if( !firmPtr->nation_recno ) continue; if( !firmPtr->should_set_power ) continue; //------- set the influence range of this firm -----// set_power(firmPtr->loc_x1, firmPtr->loc_y1, firmPtr->loc_x2, firmPtr->loc_y2, (char)firmPtr->nation_recno); } } //--------- End of function World::set_all_power ---------// //-------- Begin of function World::set_power ---------// // // xLoc1, yLoc1, - area on the map which the power should be set // xLoc2, yLoc2 // // nationRcno - nation recno // void World::set_power(int xLoc1, int yLoc1, int xLoc2, int yLoc2, int nationRecno) { //------- reset power_nation_recno first ------// int plateauResult = (get_loc((xLoc1+xLoc2)/2, (yLoc1+yLoc2)/2)->is_plateau()==1); int xLoc, yLoc, centerY, t; Location* locPtr = loc_matrix; xLoc1 = max( 0, xLoc1 - EFFECTIVE_POWER_DISTANCE+1); yLoc1 = max( 0, yLoc1 - EFFECTIVE_POWER_DISTANCE+1); xLoc2 = min( MAX_WORLD_X_LOC-1, xLoc2 + EFFECTIVE_POWER_DISTANCE-1); yLoc2 = min( MAX_WORLD_Y_LOC-1, yLoc2 + EFFECTIVE_POWER_DISTANCE-1); centerY = (yLoc1+yLoc2) / 2; for( yLoc=yLoc1 ; yLoc<=yLoc2 ; yLoc++ ) { t=abs(yLoc-centerY)/2; for( xLoc=xLoc1+t ; xLoc<=xLoc2-t ; xLoc++, locPtr++ ) { locPtr = get_loc(xLoc, yLoc); if(locPtr->sailable())//if(!locPtr->walkable()) continue; if(locPtr->is_power_off()) continue; if((locPtr->is_plateau()==1) != plateauResult) continue; if(locPtr->power_nation_recno==0) { locPtr->power_nation_recno = nationRecno; sys.map_need_redraw = 1; // request redrawing the map next time } } } } //--------- End of function World::set_power ---------// //-------- Begin of function World::restore_power ---------// // // xLoc1, yLoc1, - area on the map which the power should be restored // xLoc2, yLoc2 // // townRecno, firmRecno - either one // void World::restore_power(int xLoc1, int yLoc1, int xLoc2, int yLoc2, int townRecno, int firmRecno) { int nationRecno; if( townRecno ) { nationRecno = town_array[townRecno]->nation_recno; town_array[townRecno]->nation_recno = 0; } if( firmRecno ) { nationRecno = firm_array[firmRecno]->nation_recno; firm_array[firmRecno]->nation_recno = 0; } //------- reset power_nation_recno first ------// int xLoc, yLoc, centerY, t; Location* locPtr = loc_matrix; xLoc1 = max( 0, xLoc1 - EFFECTIVE_POWER_DISTANCE+1); yLoc1 = max( 0, yLoc1 - EFFECTIVE_POWER_DISTANCE+1); xLoc2 = min( MAX_WORLD_X_LOC-1, xLoc2 + EFFECTIVE_POWER_DISTANCE-1); yLoc2 = min( MAX_WORLD_Y_LOC-1, yLoc2 + EFFECTIVE_POWER_DISTANCE-1); centerY = (yLoc1+yLoc2) / 2; for( yLoc=yLoc1 ; yLoc<=yLoc2 ; yLoc++ ) { t=abs(yLoc-centerY)/2; for( xLoc=xLoc1+t ; xLoc<=xLoc2-t ; xLoc++, locPtr++ ) { locPtr = get_loc(xLoc, yLoc); if( locPtr->power_nation_recno==nationRecno ) { locPtr->power_nation_recno = 0; sys.map_need_redraw = 1; // request redrawing the map next time } } } //--- if some power areas are freed up, see if neighbor towns/firms should take up these power areas ----// if( sys.map_need_redraw ) // when calls set_all_power(), the nation_recno of the calling firm must be reset set_all_power(); //------- restore the nation recno of the calling town/firm -------// if( townRecno ) town_array[townRecno]->nation_recno = nationRecno; if( firmRecno ) firm_array[firmRecno]->nation_recno = nationRecno; } //--------- End of function World::restore_power ---------// //-------- Begin of function World::detect_firm_town ---------// // int World::detect_firm_town() { // ##### begin Gilbert 19/9 ########// // int rc = mouse.single_click(ZOOM_X1, ZOOM_Y1, ZOOM_X2, ZOOM_Y2, 2); if( !mouse.any_click(ZOOM_X1, ZOOM_Y1, ZOOM_X2, ZOOM_Y2, 2) ) return 0; // ##### end Gilbert 19/9 ########// //------ detect pressing on link enable/disable sign -----// Firm* firmPtr; if( firm_array.selected_recno ) { firmPtr = firm_array[firm_array.selected_recno]; 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 firmPtr->draw_detect_link_line(1) ) // 1-detect action { return 1; } } Town* townPtr; if( town_array.selected_recno ) { townPtr = town_array[town_array.selected_recno]; if( townPtr->nation_recno==nation_array.player_recno && townPtr->draw_detect_link_line(1) ) // 1-detect action { return 1; } } // ####### begin Gilbert 12/9 #########// see Power::detect_select /* //--------------- detect firm ------------------// if( rc==1 ) // left click { int mouseAbsX = mouse.cur_x - ZOOM_X1 + World::view_top_x; int mouseAbsY = mouse.cur_y - ZOOM_Y1 + World::view_top_y; int i; for( i=firm_array.size() ; i>0 ; i-- ) { if( firm_array.is_deleted(i) ) continue; firmPtr = firm_array[i]; if( m.is_touch( mouseAbsX, mouseAbsY, mouseAbsX, mouseAbsY, firmPtr->abs_x1, firmPtr->abs_y1, firmPtr->abs_x2, firmPtr->abs_y2 ) ) { power.reset_selection(); firm_array.selected_recno = i; info.disp(); // -------- sound effect -----------// if( firmPtr->nation_recno == nation_array.player_recno && se_res.mark_select_object_time() ) { se_res.sound(firmPtr->center_x, firmPtr->center_y, 1, 'F', firmPtr->firm_id, firmPtr->under_construction ? "SELU" : "SEL" ); } return 1; } } //----------- detect town section --------------// for( i=town_array.size() ; i>0 ; i-- ) { if( town_array.is_deleted(i) ) continue; townPtr = town_array[i]; if( m.is_touch( mouseAbsX, mouseAbsY, mouseAbsX, mouseAbsY, townPtr->abs_x1, townPtr->abs_y1, townPtr->abs_x2, townPtr->abs_y2 ) ) { power.reset_selection(); town_array.selected_recno = i; info.disp(); // -------- sound effect -----------// if( townPtr->nation_recno == nation_array.player_recno && se_res.mark_select_object_time() ) { se_res.sound(townPtr->center_x, townPtr->center_y, 1, 'T', 0, "SEL" ); } return 1; } } } */ return 0; } //-------- End of function World::detect_firm_town ---------// //-------- Begin of function World::earth_equake ------// void World::earth_quake() { Location *locPtr; int x,y; for(y = 0; y < max_y_loc; ++y) { locPtr = get_loc(0,y); for( x = 0; x < max_x_loc; ++x, ++locPtr) { if(locPtr->is_wall() ) { locPtr->attack_wall( weather.quake_rate(x,y) /2 ); } } } int firmDamage = 0; int firmDie = 0; int i; for( i=firm_array.size() ; i>0 ; i-- ) { if( firm_array.is_deleted(i) || !firm_res[firm_array[i]->firm_id]->buildable) continue; Firm *firmPtr = firm_array[i]; x = firmPtr->center_x; y = firmPtr->center_y; firmPtr->hit_points -= weather.quake_rate(x,y); if( firmPtr->own_firm() ) firmDamage++; if( firmPtr->hit_points <= 0) { firmPtr->hit_points = (float) 0; if( firmPtr->own_firm() ) firmDie++; se_res.sound(firmPtr->center_x, firmPtr->center_y, 1, 'F', firmPtr->firm_id, "DIE" ); firm_array.del_firm(i); } } int townDamage = 0; for( i=town_array.size() ; i>0 ; i-- ) { if( town_array.is_deleted(i) ) continue; Town *townPtr = town_array[i]; int ownTown = townPtr->nation_recno == nation_array.player_recno; short beforePopulation = townPtr->population; short causalty = weather.quake_rate(townPtr->center_x, townPtr->center_y) / 10; for( ; causalty > 0 && !town_array.is_deleted(i); --causalty ) { townPtr->kill_town_people(0); } if( town_array.is_deleted(i) ) causalty = beforePopulation; else causalty = beforePopulation - townPtr->population; if(ownTown) townDamage += causalty; } int unitDamage = 0; int unitDie = 0; for( i=unit_array.size(); i > 0; i-- ) { if( unit_array.is_deleted(i)) continue; Unit *unitPtr = unit_array[i]; // ###### begin Gilbert 30/8 ######// // no damage to air unit , sea unit or overseer if( !unitPtr->is_visible() || unitPtr->mobile_type == UNIT_AIR || unitPtr->mobile_type == UNIT_SEA) continue; // ###### end Gilbert 30/8 ######// float damage = (float) weather.quake_rate(unitPtr->cur_x_loc(),unitPtr->cur_y_loc() ) * unitPtr->max_hit_points / 200; if( damage >= unitPtr->hit_points) damage = unitPtr->hit_points -1; if( damage < (float) 5) damage = (float) 5; unitPtr->hit_points -= damage; if( unitPtr->is_own() ) unitDamage++; if( unitPtr->hit_points <= 0) { unitPtr->hit_points = (float) 0; if( unitPtr->is_own() ) unitDie++; } else { if( unit_res[unitPtr->unit_id]->solider_id && weather.quake_rate(unitPtr->cur_x_loc(),unitPtr->cur_y_loc()) >= 60) { ((UnitVehicle *)unitPtr)->dismount(); } } } news_array.earthquake_damage(unitDamage-unitDie, unitDie, townDamage, firmDamage-firmDie, firmDie); } //-------- End of function World::earth_equake ------// //-------- Begin of function World::lightning_strike ------// void World::lightning_strike(short cx, short cy, short radius) { short x, y; for( y = cy-radius; y <= cy+radius; ++y) { if( y < 0 || y >= max_y_loc) continue; for( x = cx-radius; x <= cx+radius; ++x) { if( x < 0 || x >= max_x_loc) continue; Location *locPtr = get_loc(x,y); if( locPtr->is_plant() ) { // ---- add a fire on it ------// locPtr->set_fire_str(80); // ##### begin Gilbert 11/8 #####// if( locPtr->can_set_fire() && locPtr->fire_str() < 5 ) locPtr->set_fire_str(5); // ##### end Gilbert 11/8 #####// } } } // ------ check hitting units -------// int i; for( i=unit_array.size(); i > 0; i-- ) { if( unit_array.is_deleted(i)) continue; Unit *unitPtr = unit_array[i]; // no damage to overseer if( !unitPtr->is_visible()) continue; if( unitPtr->cur_x_loc() <= cx+ radius && unitPtr->cur_x_loc() + unitPtr->sprite_info->loc_width > cx-radius && unitPtr->cur_y_loc() <= cy+radius && unitPtr->cur_y_loc() + unitPtr->sprite_info->loc_height > cy-radius ) { unitPtr->hit_points -= (float) unitPtr->sprite_info->lightning_damage / ATTACK_SLOW_DOWN; // ---- add news -------// if( unitPtr->is_own() ) news_array.lightning_damage(unitPtr->cur_x_loc(), unitPtr->cur_y_loc(), NEWS_LOC_UNIT, i, unitPtr->hit_points <= (float) 0); if( unitPtr->hit_points <= 0) unitPtr->hit_points = (float) 0; } } for( i=firm_array.size() ; i>0 ; i-- ) { if( firm_array.is_deleted(i) || !firm_res[firm_array[i]->firm_id]->buildable) continue; Firm *firmPtr = firm_array[i]; if( firmPtr->loc_x1 <= cx+radius && firmPtr->loc_x2 >= cx-radius && firmPtr->loc_y1 <= cy+radius && firmPtr->loc_y2 >= cy-radius) { firmPtr->hit_points -= (float) 50 / ATTACK_SLOW_DOWN; // ---- add news -------// if( firmPtr->own_firm() ) news_array.lightning_damage(firmPtr->center_x, firmPtr->center_y, NEWS_LOC_FIRM, i, firmPtr->hit_points <= (float) 0); // ---- add a fire on it ------// Location *locPtr = get_loc(firmPtr->center_x, firmPtr->center_y); if( locPtr->can_set_fire() && locPtr->fire_str() < 5 ) locPtr->set_fire_str(5); if( firmPtr->hit_points <= 0) { firmPtr->hit_points = (float) 0; se_res.sound(firmPtr->center_x, firmPtr->center_y, 1, 'F', firmPtr->firm_id, "DIE" ); firm_array.del_firm(i); } } } for( i=town_array.size() ; i>0 ; i-- ) { if( town_array.is_deleted(i)) continue; Town *townPtr = town_array[i]; if( townPtr->loc_x1 <= cx+radius && townPtr->loc_x2 >= cx-radius && townPtr->loc_y1 <= cy+radius && townPtr->loc_y2 >= cy-radius) { // ---- add news -------// if( townPtr->nation_recno == nation_array.player_recno ) news_array.lightning_damage(townPtr->center_x, townPtr->center_y, NEWS_LOC_TOWN, i, 0); // ---- add a fire on it ------// // ####### begin Gilbert 11/8 #########// Location *locPtr = get_loc(townPtr->center_x, townPtr->center_y); if( locPtr->can_set_fire() && locPtr->fire_str() < 5) locPtr->set_fire_str(5); // ####### end Gilbert 11/8 #########// townPtr->kill_town_people(0); } } } //-------- End of function World::lightning_strike -------// // ------- Begin of function World::visit -----------// // set the visit_level surrounding unit, town and firm void World::visit(int xLoc1, int yLoc1, int xLoc2, int yLoc2, int range, int extend) { if(config.fog_of_war) { int left = max( 0, xLoc1 - range); int top = max( 0, yLoc1 - range); int right = min( MAX_WORLD_X_LOC-1, xLoc2 + range); int bottom = min( MAX_WORLD_Y_LOC-1, yLoc2 + range); // ----- mark the visit_level of the square around the unit ------// for( int yLoc=top ; yLoc<=bottom ; yLoc++ ) { Location *locPtr = get_loc(left, yLoc); for( int xLoc=left ; xLoc<=right ; xLoc++, locPtr++ ) { locPtr->set_visited(); } } // ----- visit_level decreasing outside the visible range ------// if( extend > 0) { int visitLevel = FULL_VISIBILITY; int levelDrop = (FULL_VISIBILITY - EXPLORED_VISIBILITY) / (extend+1); xLoc1 -= range; xLoc2 += range; yLoc1 -= range; yLoc2 += range; for( ++range; extend > 0; --extend, ++range) { xLoc1--; xLoc2++; yLoc1--; yLoc2++; visitLevel -= levelDrop; visit_shell(xLoc1, yLoc1, xLoc2, yLoc2, visitLevel); } } } } // ------- End of function World::visit -----------// // ------- Begin of function World::visit_shell -----------// // set specific visit_level on the surrounding unit, town and firm void World::visit_shell(int xLoc1, int yLoc1, int xLoc2, int yLoc2, int visitLevel) { int left = max( 0, xLoc1 ); int top = max( 0, yLoc1 ); int right = min( MAX_WORLD_X_LOC-1, xLoc2); int bottom = min( MAX_WORLD_Y_LOC-1, yLoc2); // ------- top side ---------// if( yLoc1 >= 0) { Location *locPtr = get_loc( left, yLoc1); for( int x = left; x <= right; ++x, ++locPtr) locPtr->set_visited(visitLevel); } // ------- bottom side ---------// if( yLoc2 < max_y_loc) { Location *locPtr = get_loc( left, yLoc2); for( int x = left; x <= right; ++x, ++locPtr) locPtr->set_visited(visitLevel); } // ------- left side -----------// if( xLoc1 >= 0) { for( int y = top; y <= bottom; ++y) { get_loc(xLoc1,y)->set_visited(visitLevel); } } // ------- right side -----------// if( xLoc2 < max_x_loc) { for( int y = top; y <= bottom; ++y) { get_loc(xLoc2,y)->set_visited(visitLevel); } } } // ------- End of function World::visit_shell -----------// //------- Begin of function World::process_visibility -----------// void World::process_visibility() { if( config.fog_of_war ) { // ###### begin Gilbert 13/10 ########// //for( int y = 0; y < max_y_loc; ++y) //{ // Location *locPtr = get_loc(0,y); // for( int x = 0; x < max_x_loc; ++x, ++locPtr) // { // locPtr->dec_visibility(); // } //} int count = max_x_loc * max_y_loc; const int sizeOfLoc = sizeof(Location); unsigned char *locVisitLevel = &get_loc(0,0)->visit_level; unsigned char decVisitLevel = EXPLORED_VISIBILITY*2+1; /* Original Visual C++ assembly code for reference _asm { mov ecx, count mov ebx, locVisitLevel mov edx, sizeOfLoc mov ah, decVisitLevel process_visit_level_1: mov al,[ebx] cmp al,ah // if(al > EXPLORED_VISIBILITY*2) al--; cmc sbb al,0 mov [ebx],al add ebx, edx loop process_visit_level_1 } */ __asm__ __volatile__ ( "movb %0, %%ah\n" "process_visit_level_1:\n\t" "movb (%%ebx), %%al\n\t" "cmpb %%ah, %%al\n\t" "cmc\n\t" "sbbb $0, %%al\n\t" "movb %%al, (%%ebx)\n\t" "addl %%edx, %%ebx\n\t" "loop process_visit_level_1\n\t" : : "m"(decVisitLevel), "b"(locVisitLevel), "c"(count), "d"(sizeOfLoc) : "%eax" ); // ###### end Gilbert 13/10 ########// } } //------- End of function World::process_visibility -----------// //--------- Begin of function World::disp_next --------// // // Display the next object of the same type. // // seekDir : -1 - display the previous one in the list. // 1 - display the next one in the list. // // sameNation - whether display the next object of the same // nation only or of any nation. // void World::disp_next(int seekDir, int sameNation) { //--- if the selected one is a unit ----// if( unit_array.selected_recno ) { int unitRecno = unit_array.selected_recno; Unit* unitPtr = unit_array[unit_array.selected_recno]; int unitClass = unit_res[unitPtr->unit_id]->unit_class; int nationRecno = unitPtr->nation_recno; while(1) { if( seekDir < 0 ) { unitRecno--; if( unitRecno < 1 ) unitRecno = unit_array.size(); } else { unitRecno++; if( unitRecno > unit_array.size() ) unitRecno = 1; } if( unit_array.is_deleted(unitRecno) ) continue; unitPtr = unit_array[unitRecno]; if( !unitPtr->is_visible() ) continue; //--- check if the location of the unit has been explored ---// if( !world.get_loc(unitPtr->next_x_loc(), unitPtr->next_y_loc())->explored() ) continue; //-------- if are of the same nation --------// if( sameNation && unitPtr->nation_recno != nationRecno ) continue; //---------------------------------// if( unit_res[unitPtr->unit_id]->unit_class == unitClass ) { power.reset_selection(); unitPtr->selected_flag = 1; unit_array.selected_recno = unitRecno; unit_array.selected_count++; world.go_loc( unitPtr->cur_x_loc(), unitPtr->cur_y_loc() ); return; } //--- if the recno loops back to the starting one ---// if( unitRecno == unit_array.selected_recno ) break; } } //--- if the selected one is a firm ----// if( firm_array.selected_recno ) { int firmRecno = firm_array.selected_recno; Firm* firmPtr = firm_array[firm_array.selected_recno]; int firmId = firmPtr->firm_id; int nationRecno = firmPtr->nation_recno; while(1) { if( seekDir < 0 ) { firmRecno--; if( firmRecno < 1 ) firmRecno = firm_array.size(); } else { firmRecno++; if( firmRecno > firm_array.size() ) firmRecno = 1; } if( firm_array.is_deleted(firmRecno) ) continue; firmPtr = firm_array[firmRecno]; //-------- if are of the same nation --------// if( sameNation && firmPtr->nation_recno != nationRecno ) continue; //--- check if the location of this firm has been explored ---// if( !world.get_loc(firmPtr->center_x, firmPtr->center_y)->explored() ) continue; //---------------------------------// if( firmPtr->firm_id == firmId ) { power.reset_selection(); firm_array.selected_recno = firmRecno; world.go_loc( firmPtr->center_x, firmPtr->center_y ); return; } //--- if the recno loops back to the starting one ---// if( firmRecno == firm_array.selected_recno ) break; } } //--- if the selected one is a town ----// if( town_array.selected_recno ) { int townRecno = town_array.selected_recno; int nationRecno = town_array[townRecno]->nation_recno; Town* townPtr; while(1) { if( seekDir < 0 ) { townRecno--; if( townRecno < 1 ) townRecno = town_array.size(); } else { townRecno++; if( townRecno > town_array.size() ) townRecno = 1; } if( town_array.is_deleted(townRecno) ) continue; townPtr = town_array[townRecno]; //-------- if are of the same nation --------// if( sameNation && townPtr->nation_recno != nationRecno ) continue; //--- check if the location of this town has been explored ---// if( !world.get_loc(townPtr->center_x, townPtr->center_y)->explored() ) continue; //---------------------------------// power.reset_selection(); town_array.selected_recno = townRecno; world.go_loc( townPtr->center_x, townPtr->center_y ); return; //--- if the recno loops back to the starting one ---// if( townRecno == town_array.selected_recno ) break; } } //--- if the selected one is a natural resource site ----// if( site_array.selected_recno ) { int siteRecno = site_array.selected_recno; Site* sitePtr = site_array[site_array.selected_recno]; int siteType = sitePtr->site_type; while(1) { if( seekDir < 0 ) { siteRecno--; if( siteRecno < 1 ) siteRecno = site_array.size(); } else { siteRecno++; if( siteRecno > site_array.size() ) siteRecno = 1; } if( site_array.is_deleted(siteRecno) ) continue; sitePtr = site_array[siteRecno]; //--- check if the location of this site has been explored ---// if( !world.get_loc(sitePtr->map_x_loc, sitePtr->map_y_loc)->explored() ) continue; //---------------------------------// if( sitePtr->site_type == siteType ) { power.reset_selection(); site_array.selected_recno = siteRecno; world.go_loc( sitePtr->map_x_loc, sitePtr->map_y_loc ); return; } //--- if the recno loops back to the starting one ---// if( siteRecno == site_array.selected_recno ) break; } } } //----------- End of function World::disp_next --------// #ifdef DEBUG3 //--------- Begin of function World::get_loc --------// // Location* World::get_loc(int xLoc, int yLoc) { err_when( xLoc<0 || xLoc>=MAX_WORLD_X_LOC ); err_when( yLoc<0 || yLoc>=MAX_WORLD_Y_LOC ); return loc_matrix + MAX_WORLD_X_LOC * yLoc + xLoc; } //----------- End of function World::get_loc --------// //--------- Begin of function World::get_region_id --------// // BYTE World::get_region_id(int xLoc, int yLoc) { err_when( xLoc<0 || xLoc>=MAX_WORLD_X_LOC ); err_when( yLoc<0 || yLoc>=MAX_WORLD_Y_LOC ); return loc_matrix[MAX_WORLD_X_LOC*yLoc+xLoc].region_id; } //----------- End of function World::get_region_id --------// #endif // ####### begin Gilbert 25/7 #########// // return true if any location adjacent to (x,y) is on a particular region int World::is_adjacent_region(int x, int y, int regionId) { if( y > 0 ) { if( x > 0 ) { if( get_region_id(x-1,y-1) == regionId ) return 1; } if( get_region_id(x,y-1) == regionId ) return 1; if( x < max_x_loc-1 ) { if( get_region_id(x+1,y-1) == regionId ) return 1; } } if( x > 0 ) { if( get_region_id(x-1,y) == regionId ) return 1; } if( x < max_x_loc-1 ) { if( get_region_id(x+1,y) == regionId ) return 1; } if( y < max_y_loc-1) { if( x > 0 ) { if( get_region_id(x-1,y+1) == regionId ) return 1; } if( get_region_id(x,y+1) == regionId ) return 1; if( x < max_x_loc-1 ) { if( get_region_id(x+1,y+1) == regionId ) return 1; } } return 0; } // ####### end Gilbert 25/7 #########//