123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703704705706707708709710711712713714715716717718719720721722723724725726727728729730731732733734735736737738739740741742743744745746747748749750751752753754755756 |
- /*
- * 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 <http://www.gnu.org/licenses/>.
- *
- */
- //Filename : OAI_SEEK.CPP
- //Description: AI - action progressing functions
- #include <ALL.h>
- #include <OUNIT.h>
- #include <OF_MINE.h>
- #include <OF_FACT.h>
- #include <OF_HARB.h>
- #include <OTOWN.h>
- #include <OSITE.h>
- #include <ONATION.h>
- //--------- Begin of function Nation::seek_mine --------//
- //
- // <short&> xLoc, yLoc - reference vars for returning the building
- // location.
- // <short&> refXLoc, refYLoc - reference vars for returning the exact
- // location of the raw material.
- //
- // return: <int> >0 the raw id. of the site.
- // ==0 no suitable site found.
- //
- int Nation::seek_mine(short& xLoc, short& yLoc, short& refXLoc, short& refYLoc)
- {
- err_when( site_array.untapped_raw_count < 0 );
- if( site_array.untapped_raw_count==0 )
- return 0;
- int raw_kind_mined[MAX_RAW], i;
- Firm *firmPtr;
- FirmMine *minePtr;
- //-----------------------------------------------------------------//
- // count each kind of raw material that is being mined
- //-----------------------------------------------------------------//
- memset(raw_kind_mined, 0, sizeof(int)*MAX_RAW);
- for(i=0; i<ai_mine_count; i++)
- {
- firmPtr = firm_array[ai_mine_array[i]];
- minePtr = firmPtr->cast_to_FirmMine();
- if( minePtr->raw_id>=1 && minePtr->raw_id<=MAX_RAW )
- raw_kind_mined[minePtr->raw_id-1]++;
- }
- //-------------------- define parameters ----------------------//
- FirmInfo *firmInfo = firm_res[FIRM_MINE];
- Location *locPtr, *siteLocPtr;
- Site *sitePtr;
- Town *townPtr;
- int nearSite[MAX_RAW], minDist[MAX_RAW], townWithMine[MAX_RAW];
- short buildXLoc[MAX_RAW], buildYLoc[MAX_RAW];
- short dist;
- int canBuild, connected, allHave;
- int j, k, siteId;
- memset(townWithMine, 0, sizeof(int)*MAX_RAW);
- memset(nearSite, 0, sizeof(int)*MAX_RAW);
- memset(buildXLoc, 0, sizeof(short)*MAX_RAW);
- memset(buildYLoc, 0, sizeof(short)*MAX_RAW);
- for(i=0; i<MAX_RAW; i++)
- minDist[i] = 0x7FFFFF;
- //--------------------------------------------//
- // scan for the site array
- //--------------------------------------------//
- for(i=site_array.size(); i>0; i--)
- {
- if(site_array.is_deleted(i))
- continue;
- sitePtr = site_array[i];
- if( sitePtr->site_type != SITE_RAW )
- continue;
- siteLocPtr = world.get_loc(sitePtr->map_x_loc, sitePtr->map_y_loc);
- if(!siteLocPtr->can_build_firm())
- continue;
- siteId = sitePtr->object_id - 1;
- err_when(siteId<0 || siteId>MAX_RAW);
- if(townWithMine[siteId])
- continue; // a site connected to town is found before
- //--------------------------------------------//
- // continue if action to this site already exist
- //--------------------------------------------//
- if(is_action_exist(-1, -1, sitePtr->map_x_loc, sitePtr->map_y_loc, ACTION_AI_BUILD_FIRM, FIRM_MINE))
- continue;
- for(j=0; j<ai_town_count; j++)
- {
- townPtr = town_array[ai_town_array[j]];
- locPtr = world.get_loc(townPtr->loc_x1, townPtr->loc_y1);
- //-********* codes to move to other territory ***********-//
- if(siteLocPtr->region_id!=locPtr->region_id)
- continue; // not on the same territory
- dist = m.points_distance(sitePtr->map_x_loc, sitePtr->map_y_loc, townPtr->center_x, townPtr->center_y);
- //-------------------------------------------------------------------------//
- // check whether a mine is already connected to this town, if so, use it
- //-------------------------------------------------------------------------//
- for(connected=0, k=townPtr->linked_firm_count-1; k>=0; k--)
- {
- err_when(!townPtr->linked_firm_array[k] || firm_array.is_deleted(townPtr->linked_firm_array[k]));
- firmPtr = firm_array[townPtr->linked_firm_array[k]];
- if(firmPtr->nation_recno==nation_recno && firmPtr->firm_id==FIRM_MINE)
- {
- connected++;
- break;
- }
- }
- //-------------------------------------------------------------------------//
- // calculate the minimum distance from own towns
- //-------------------------------------------------------------------------//
- if(dist<minDist[siteId] || (connected && dist<=EFFECTIVE_FIRM_TOWN_DISTANCE))
- {
- //------ can build or not ----------//
- canBuild = 0;
- for(int ix=sitePtr->map_x_loc-firmInfo->loc_width+1; ix<=sitePtr->map_x_loc && !canBuild; ix++)
- {
- if(ix<0 || ix>=MAX_WORLD_X_LOC)
- continue;
- for(int iy=sitePtr->map_y_loc-firmInfo->loc_height+1; iy<=sitePtr->map_y_loc && !canBuild; iy++)
- {
- if(iy<0 || iy>=MAX_WORLD_Y_LOC)
- continue;
- if(world.can_build_firm(ix, iy, FIRM_MINE))
- {
- canBuild++;
- buildXLoc[siteId] = ix;
- buildYLoc[siteId] = iy;
- break;
- }
- }
- }
- if(canBuild)
- {
- nearSite[siteId] = i;
- minDist[siteId] = dist;
-
- if(connected && dist<=EFFECTIVE_FIRM_TOWN_DISTANCE)
- townWithMine[siteId]++;
- }
- }
- }
- for(allHave=1, j=0; j<MAX_RAW; j++)
- {
- if(!townWithMine[j])//if(!nearSite[j])
- {
- allHave = 0;
- break;
- }
- }
- if(allHave)
- break; // sites of each raw material have been found
- }
-
- //---------------------------------------------------------------------------//
- // determine which raw material is the best choice to build
- // Note: a better sorting algorithm should be used if there are many kind of
- // raw material
- //---------------------------------------------------------------------------//
- int weight, pos; // weight is the such kind of material mined, pos is the position in the array
- int siteRecno = 0; // siteRecno is the recno of site to build
- int withoutThisRaw = 0; // withoutThisRaw shows that this raw material is strongly recommended
- int closestDist=0x7FFFFF;
-
- for(pos=-1, weight=0x7FFFFF, j=0 ;j<MAX_RAW; j++)
- {
- if(!nearSite[j])
- continue; // no such kind of raw material
- if(!raw_kind_mined[j]) // no such kind of material and there is a possible site
- {
- if(withoutThisRaw)
- {
- if(minDist[j]<closestDist) // more than one kind of material we don't have
- {
- siteRecno = nearSite[j];
- closestDist = minDist[j];
- pos = j;
- }
- }
- else
- {
- siteRecno = nearSite[j];
- closestDist = minDist[j];
- withoutThisRaw++;
- pos = j;
- }
- }
- else if(!withoutThisRaw && weight>raw_kind_mined[j]) // scan for the kind of material with least num of this site
- {
- weight = raw_kind_mined[j];
- pos = j;
- }
- }
- if(!siteRecno && pos>=0)
- siteRecno = nearSite[pos];
-
- if(siteRecno)
- {
- sitePtr = site_array[siteRecno];
- xLoc = buildXLoc[pos];
- yLoc = buildYLoc[pos];
- refXLoc = sitePtr->map_x_loc;
- refYLoc = sitePtr->map_y_loc;
- err_when((xLoc-refXLoc)>=firm_res[FIRM_MINE]->loc_width || (yLoc-refYLoc)>=firm_res[FIRM_MINE]->loc_height);
- //--------------------------------------------------------------//
- // do some adjustment such that the firm will be built far away
- // from other firms by at least one step.
- //--------------------------------------------------------------//
- seek_best_build_mine_location(xLoc, yLoc, sitePtr->map_x_loc, sitePtr->map_y_loc);
- err_when((xLoc-refXLoc)>=firm_res[FIRM_MINE]->loc_width || (yLoc-refYLoc)>=firm_res[FIRM_MINE]->loc_height);
- return sitePtr->object_id; // the raw id.
- }
- return 0;
- }
- //---------- End of function Nation::seek_mine --------//
- //----- Begin of function Nation::seek_best_build_mine_location -----//
- //
- // <short&> xLoc - a possible x location to build the mine, the final location is also returned by this reference
- // <short&> yLoc - a possible y location to build the mine.
- //
- // <short> mapXLoc - the x location of the raw material
- // <short> mapYLoc - the y location of the raw material
- //
- void Nation::seek_best_build_mine_location(short& xLoc, short& yLoc, short mapXLoc, short mapYLoc)
- {
- //--------------- define parameters -----------------//
- FirmInfo *firmInfo = firm_res[FIRM_MINE];
- int weight = 0, maxWeight = 0;
- short xLeftLimit = mapXLoc-firmInfo->loc_width+1;
- short yLeftLimit = mapYLoc-firmInfo->loc_height+1;
- short resultXLoc = xLoc;
- short resultYLoc = yLoc;
- short ix, iy;
- for(ix=xLeftLimit; ix<=mapXLoc; ix++)
- {
- if(ix<0 || ix>=MAX_WORLD_X_LOC)
- continue;
- for(iy=yLeftLimit; iy<=mapYLoc; iy++)
- {
- if(iy<0 || iy>=MAX_WORLD_Y_LOC)
- continue;
- //---------------------------------------------------------------//
- // remove previous checked and useless locaton
- // Since all the possible location is checked from the top left
- // to the bottom right, the previous checked location should all
- // be impossible to build the mine.
- //---------------------------------------------------------------//
- if(ix<xLoc && iy<yLoc)
- continue;
- if(world.can_build_firm(ix, iy, FIRM_MINE))
- {
- //----------------------------------------//
- // calculate weight
- //----------------------------------------//
- weight = 0;
- cal_location_score(ix, iy, firmInfo->loc_width, firmInfo->loc_height, weight);
- if(weight>maxWeight)
- {
- resultXLoc = ix;
- resultYLoc = iy;
- if(weight == MAX_SCORE) // very good locaton, stop checking
- break;
- maxWeight = weight;
- }
- }
- }
- }
- xLoc = resultXLoc;
- yLoc = resultYLoc;
- }
- //---------- End of function Nation::seek_best_build_mine_location --------//
- //--------- Begin of function Nation::cal_location_score --------//
- // Called by seek_best_build_mine_location() to calculate a specifed
- // location score to build the mine.
- //
- // <short> x1 - the upper left corner x location of the firm
- // <short> y1 - the upper left corner y location of the firm
- // <short> width - the width of the firm
- // <short> height - the height of the firm
- // <short&> score - return the location score
- //
- void Nation::cal_location_score(short x1, short y1, short width, short height, int& score)
- {
- //-----------------------------------------------------------------//
- // the score is calculated as follows, for instance, the firm is
- // 2x2 in dimension
- //
- // LU U U RU L--left, R--right, U--upper, O--lower
- // L x x R
- // L x x R
- // LO O O RO
- //
- // if any L can build, score += 1, if all set of L can build the total
- // score of this edge is 100. For each corner, the score is 50 if
- // can build. Thus, the max. score == 600
- //
- //-----------------------------------------------------------------//
- short x, y, i, count;
- score = 0;
- //---------- left edge ---------//
- if((x=x1-1)>=0)
- {
- for(i=0, count=0; i<height; i++)
- {
- if(world.get_loc(x, y1+i)->can_build_firm())
- count++;
- }
- score += (count==height) ? 100 : count;
- }
-
- //---------- upper edge ---------//
- if((y=y1-1)>=0)
- {
- for(i=0, count=0; i<width; i++)
- {
- if(world.get_loc(x1+i, y)->can_build_firm())
- count++;
- }
- score += (count==width) ? 100 : count;
- }
- //---------- right edge ---------//
- if((x=x1+width)<MAX_WORLD_X_LOC)
- {
- for(i=0, count=0; i<height; i++)
- {
- if(world.get_loc(x, y1+i)->can_build_firm())
- count++;
- }
- score += (count==height) ? 100 : count;
- }
-
- //----------- lower edge -----------//
- if((y=y1+height)<MAX_WORLD_Y_LOC)
- {
- for(i=0, count=0; i<width; i++)
- {
- if(world.get_loc(x1+i, y)->can_build_firm())
- count++;
- }
- score += (count==width) ? 100 : count;
- }
- //------------------------------------------//
- // extra score
- //------------------------------------------//
- //------- upper left corner -------//
- if(x1>0 && y1>0 && world.get_loc(x1-1, y1-1)->can_build_firm())
- score += 50;
- //------- upper right corner ---------//
- if(x1<MAX_WORLD_X_LOC-1 && y1>0 && world.get_loc(x1+1, y1-1)->can_build_firm())
- score += 50;
- //----------- lower left corner ----------//
- if(x1>0 && y1<MAX_WORLD_Y_LOC-1 && world.get_loc(x1-1, y1+1)->can_build_firm())
- score += 50;
- //------- lower right corner ---------//
- if(x1<MAX_WORLD_X_LOC-1 && y1<MAX_WORLD_Y_LOC-1 && world.get_loc(x1+1, y1+1)->can_build_firm())
- score += 50;
- }
- //---------- End of function Nation::cal_location_score --------//
- //----------- Begin of function Nation::find_best_firm_loc ----------//
- //
- // Determine the location of a new firm. It's best to have the
- // new firm within the refective range of: towns, factories and
- // mines.
- //
- // <short> buildFirmId - id. of the firm to be built
- // <short> refXLoc, refYLoc - either the location of a town or a firm,
- // the market must be built next to it.
- // <short&> resultXLoc, resultYLoc - result location of the firm.
- //
- // return: <int> 1 - succeed, 0 - fail
- //
- int Nation::find_best_firm_loc(short buildFirmId, short refXLoc, short refYLoc, short& resultXLoc, short& resultYLoc)
- {
- Location *locPtr = world.get_loc(refXLoc, refYLoc);
- short centerX, centerY, refX1, refY1, refX2, refY2;
- //-------- get the refective area ---------//
- int originFirmRecno=0, originTownRecno=0;
- Firm* firmPtr;
- Town* townPtr;
- BYTE buildRegionId = locPtr->region_id;
- int buildIsPlateau = locPtr->is_plateau();
- if( locPtr->is_firm() )
- {
- originFirmRecno = locPtr->firm_recno();
- firmPtr = firm_array[originFirmRecno];
- centerX = firmPtr->center_x;
- centerY = firmPtr->center_y;
- refX1 = centerX - EFFECTIVE_FIRM_FIRM_DISTANCE;
- refY1 = centerY - EFFECTIVE_FIRM_FIRM_DISTANCE;
- refX2 = centerX + EFFECTIVE_FIRM_FIRM_DISTANCE;
- refY2 = centerY + EFFECTIVE_FIRM_FIRM_DISTANCE;
- if( firmPtr->firm_id == FIRM_HARBOR )
- {
- buildRegionId = ((FirmHarbor*)firmPtr)->land_region_id;
- buildIsPlateau = 0;
- }
- }
- else if( locPtr->is_town() )
- {
- originTownRecno = locPtr->town_recno();
- townPtr = town_array[originTownRecno];
- centerX = townPtr->center_x;
- centerY = townPtr->center_y;
- refX1 = centerX - EFFECTIVE_FIRM_TOWN_DISTANCE;
- refY1 = centerY - EFFECTIVE_FIRM_TOWN_DISTANCE;
- refX2 = centerX + EFFECTIVE_FIRM_TOWN_DISTANCE;
- refY2 = centerY + EFFECTIVE_FIRM_TOWN_DISTANCE;
- }
- else
- err_here();
- //------------------------------------------------------//
- FirmInfo* firmInfo = firm_res[buildFirmId];
- int firmLocWidth = firmInfo->loc_width;
- int firmLocHeight = firmInfo->loc_height;
- refX1 -= firmLocWidth/2; // since we use loc_x1 as the building reference, we need to shift it so it will match the use of center_x in effective distance
- refY1 -= firmLocHeight/2;
- refX1 = max(0, refX1);
- refY1 = max(0, refY1);
- if( refX2 - firmLocWidth/2 >= MAX_WORLD_X_LOC )
- refX2 = MAX_WORLD_X_LOC-1;
- else
- refX2 -= firmLocWidth/2;
- if( refY2 - firmLocHeight/2 >= MAX_WORLD_Y_LOC )
- refY2 = MAX_WORLD_Y_LOC-1;
- else
- refY2 -= firmLocHeight/2;
- err_when( refX2 >= MAX_WORLD_X_LOC );
- err_when( refY2 >= MAX_WORLD_Y_LOC );
- //-------- build a matrix on the refective area ---------//
- int refWidth=refX2-refX1+1, refHeight=refY2-refY1+1;
- short* refMatrix = (short*) mem_add( sizeof(short) * refWidth * refHeight );
- short* refMatrixPtr;
- //------ initialize the weights of the matrix ------//
- int xLoc, yLoc; // inner locations in the matrix receives more weights than outer locations do
- int t1, t2;
- for( yLoc=refY1 ; yLoc<=refY2 ; yLoc++ )
- {
- refMatrixPtr = refMatrix + (yLoc-refY1)*refWidth;
- locPtr = world.get_loc( refX1, yLoc );
- for( xLoc=refX1 ; xLoc<=refX2 ; xLoc++, refMatrixPtr++, locPtr++ )
- {
- t1 = abs(xLoc-centerX);
- t2 = abs(yLoc-centerY);
- if( locPtr->region_id != buildRegionId ||
- locPtr->is_plateau() != buildIsPlateau ||
- locPtr->is_power_off() )
- {
- *refMatrixPtr = -1000;
- }
- else
- {
- *refMatrixPtr = 10-max(t1, t2); // it's negative value, and the value is lower for the outer ones
- }
- }
- }
- //----- calculate weights of the locations in the matrix ----//
- int xLocB, yLocB, weightAdd, weightReduce;
- short refBX1, refBY1, refBX2, refBY2;
- short refCX1, refCY1, refCX2, refCY2;
- for( yLoc=refY1 ; yLoc<=refY2 ; yLoc++ )
- {
- locPtr = world.get_loc(refX1, yLoc);
- for( xLoc=refX1 ; xLoc<=refX2 ; xLoc++, locPtr++ )
- {
- if( locPtr->region_id != buildRegionId ||
- locPtr->is_plateau() != buildIsPlateau ||
- locPtr->is_power_off() )
- {
- continue;
- }
- //------- if there is a firm on the location ------//
- weightAdd = 0;
- weightReduce = 0;
- if( locPtr->is_firm() )
- {
- firmPtr = firm_array[locPtr->firm_recno()];
- if( buildFirmId==FIRM_MARKET || buildFirmId==FIRM_FACTORY ) // only factories & market places need building close to other firms
- {
- int rc = 1;
- if( firmPtr->nation_recno != nation_recno )
- rc = 0;
- //----- check if the firm is of the right type ----//
- if( buildFirmId==FIRM_MARKET ) // build a market place close to mines and factories
- {
- if( firmPtr->firm_id!=FIRM_MINE && firmPtr->firm_id!=FIRM_FACTORY ) // market places should be built close to factories and mines and they are the only two firms that influence the location of the market place
- rc = 0;
- }
- else if( buildFirmId==FIRM_FACTORY ) // build a factory close to mines and market places
- {
- if( firmPtr->firm_id!=FIRM_MINE && firmPtr->firm_id!=FIRM_MARKET ) // market places should be built close to factories and mines and they are the only two firms that influence the location of the market place
- rc = 0;
- }
- //------------------------------------------/
- if( rc )
- {
- refBX1 = firmPtr->center_x - EFFECTIVE_FIRM_FIRM_DISTANCE;
- refBY1 = firmPtr->center_y - EFFECTIVE_FIRM_FIRM_DISTANCE;
- refBX2 = firmPtr->center_x + EFFECTIVE_FIRM_FIRM_DISTANCE;
- refBY2 = firmPtr->center_y + EFFECTIVE_FIRM_FIRM_DISTANCE;
- weightAdd = 30;
- }
- }
- refCX1 = firmPtr->loc_x1-1; // add negative weights on space around this firm
- refCY1 = firmPtr->loc_y1-1; // so to prevent firms from building right next to the firm
- refCX2 = firmPtr->loc_x2+1; // and leave some space for walking path.
- refCY2 = firmPtr->loc_y2+1;
- weightReduce = 20;
- }
- //------- if there is a town on the location ------//
- else if( locPtr->is_town() )
- {
- townPtr = town_array[locPtr->town_recno()];
- refBX1 = townPtr->center_x - EFFECTIVE_FIRM_TOWN_DISTANCE;
- refBY1 = townPtr->center_y - EFFECTIVE_FIRM_TOWN_DISTANCE;
- refBX2 = townPtr->center_x + EFFECTIVE_FIRM_TOWN_DISTANCE;
- refBY2 = townPtr->center_y + EFFECTIVE_FIRM_TOWN_DISTANCE;
- weightAdd = townPtr->population*2;
- //----- if the town is not our own -----//
- if(townPtr->nation_recno != nation_recno)
- {
- if( townPtr->nation_recno==0 ) // it's an independent town
- weightAdd = weightAdd * (100-townPtr->average_resistance(nation_recno)) / 100;
- else // more friendly nations get higher weights
- {
- int relationStatus = get_relation_status(townPtr->nation_recno);
- if( relationStatus >= NATION_NEUTRAL )
- weightAdd = weightAdd * (relationStatus-NATION_NEUTRAL+1) / 4;
- }
- }
- refCX1 = townPtr->loc_x1-1; // add negative weights on space around this firm
- refCY1 = townPtr->loc_y1-1; // so to prevent firms from building right next to the firm
- refCX2 = townPtr->loc_x2+1; // and leave some space for walking path.
- refCY2 = townPtr->loc_y2+1;
- weightReduce = 100;
- }
- else
- continue;
- //------ add weights to the matrix ------//
- if( weightAdd )
- {
- for( yLocB=max(refY1,refBY1) ; yLocB<=min(refY2,refBY2) ; yLocB++ )
- {
- xLocB = max(refX1,refBX1);
- refMatrixPtr = refMatrix + (yLocB-refY1)*refWidth + (xLocB-refX1);
- for( ; xLocB<=min(refX2,refBX2) ; xLocB++ )
- {
- *refMatrixPtr++ += weightAdd;
- }
- }
- }
- //------ reduce weights from the matrix ------//
- if( weightReduce )
- {
- for( yLocB=max(refY1,refCY1) ; yLocB<=min(refY2,refCY2) ; yLocB++ )
- {
- xLocB = max(refX1,refCX1);
- refMatrixPtr = refMatrix + (yLocB-refY1)*refWidth + (xLocB-refX1);
- for( ; xLocB<=min(refX2,refCX2) ; xLocB++ )
- {
- *refMatrixPtr++ -= weightReduce;
- }
- }
- }
- }
- }
- //------ select the best building site in the matrix -------//
- resultXLoc = -1;
- resultYLoc = -1;
- short thisWeight, bestWeight=0;
- refX2 -= firmLocWidth-1; // do not scan beyond the border
- refY2 -= firmLocHeight-1;
- for( yLoc=refY1 ; yLoc<=refY2 ; yLoc++ )
- {
- for( xLoc=refX1 ; xLoc<=refX2 ; xLoc++ )
- {
- if( world.get_region_id(xLoc, yLoc) != buildRegionId ||
- !world.can_build_firm(xLoc, yLoc, buildFirmId) )
- {
- continue;
- }
- //---- calculate the average weight of a firm area ----//
- int totalWeight=0;
- refMatrixPtr = refMatrix + (yLoc-refY1)*refWidth + (xLoc-refX1);
- for( int yCount=0 ; yCount<firmLocHeight ; yCount++ )
- {
- for( int xCount=0 ; xCount<firmLocWidth ; xCount++ )
- {
- totalWeight += *refMatrixPtr++;
- }
- refMatrixPtr += refWidth-firmLocWidth;
- }
- //------- compare the weights --------//
- thisWeight = totalWeight / (firmLocWidth*firmLocHeight);
- if( thisWeight > bestWeight )
- {
- bestWeight = thisWeight;
- resultXLoc = xLoc;
- resultYLoc = yLoc;
- }
- }
- }
- //------ release the refective matrix -----//
- mem_del( refMatrix );
- return resultXLoc >= 0;
- }
- //-------- End of function Nation::find_best_firm_loc --------//
|