//----- Begin of function FirmMarket::update_trade_link -----// // // Update the status of links to harbors and towns based // on the current trade treaty status. // void FirmMarket::update_trade_link() { Nation* ownNation = nation_array[nation_recno]; int tradeTreaty; //------ update links to towns -----// Town* townPtr; for( int i=0 ; i<linked_town_count ; i++ ) { townPtr = town_array[linked_town_array[i]]; if( !townPtr->nation_recno ) continue; if( townPtr->nation_recno ) { tradeTreaty = ownNation->get_relation(townPtr->nation_recno)->trade_treaty || townPtr->nation_recno==nation_recno; } else // if this is an independent town, it buys goods from the market if its resistance towards the nation is < 30 { tradeTreaty = townPtr->resistance(nation_recno) <= INDEPENDENT_LINK_RESISTANCE; } if( linked_town_enable_array[i] != (tradeTreaty ? LINK_EE : LINK_DD) ) toggle_town_link( i+1, tradeTreaty, COMMAND_AUTO, 1 ); // 1-toggle both side } }
//------- Begin of function Firm::being_killed ------// // // <BaseObj*> attackerObj - this can be NULL if the attacker no longer // exists (the damage is caused by a bullet.) // void Firm::being_killed(BaseObj* attackerObj) { se_res.sound(center_x, center_y, 1, 'F', firm_id, "DIE" ); if( nation_recno == nation_array.player_recno && attackerObj ) //BUGHERE news_array.firm_destroyed(firm_recno, attackerObj); // ######## begin Gilbert 17/6 ########// if( nation_recno == 0 && firm_id == FIRM_LAIR && is_monster() ) { news_array.monster_firm_destroyed( monster_id(), center_x, center_y ); } // ######## end Gilbert 17/6 ########// if( nation_recno ) { if( attackerObj && attackerObj->nation_recno ) nation_array[attackerObj->nation_recno]->enemy_firm_destroyed++; if( nation_recno ) nation_array[nation_recno]->own_firm_destroyed++; } //-----------------------------------------// if( attackerObj && attackerObj->nation_recno ) { Nation* attackerNation = nation_array[attackerObj->nation_recno]; //-- destroying a monster firm raise the attacking nation's reputation --// if( is_monster() ) { float repIncrease = (float) max_hit_points() / 600; //-- if the lair is enslaving the towns, increase the reputation bonus --// if( cast_to_FirmLair() ) { int tributeAmount = cast_to_FirmLair()->collect_town_tribute(0); repIncrease += (float) tributeAmount / 600; } attackerNation->change_reputation(repIncrease); //--- when destroying an enslaving Fryhtan lair, the independent towns enslaved by it will reduce its resistance towards you by 30 points ---// if( cast_to_FirmLair() ) { int i; Town* townPtr; for( i=0 ; i<linked_town_count ; i++ ) { if(town_array.is_deleted(linked_town_array[i])) continue; townPtr = town_array[linked_town_array[i]]; //--- if it is a linked independent town ---// if( townPtr->nation_recno == 0 && // ####### begin Gilbert 9/3 ########// nation_recno && // ####### end Gilbert 9/3 ########// townPtr->resistance(nation_recno) < MONSTER_COLLECT_TOWN_TRIBUTE_LOYALTY ) { townPtr->change_resistance(attackerObj->nation_recno, -30); } } } } //------ destroyng a building gives money ------// float killMoney = (float) (firm_res[firm_id]->setup_cost + firm_recno%100) / 3; // add some randomness attackerNation->add_income( INCOME_TREASURE, killMoney ); attackerNation->increased_cash = killMoney; } firm_array.del_firm(firm_recno); }
//------- Begin of function FirmMarket::think_export_product -----------// // // Think about exporting products from this market to another market. // int FirmMarket::think_export_product() { //--- first check if there is any excessive supply for export ---// int exportProductId = 0; MarketGoods *marketGoods = market_goods_array; for( int i=0 ; i<MAX_MARKET_GOODS ; i++, marketGoods++ ) { if( marketGoods->product_raw_id ) { if( marketGoods->stock_qty > MAX_MARKET_STOCK * 3 / 4 && marketGoods->month_demand < marketGoods->supply_30days() / 2 ) // the supply is at least double of the demand { exportProductId = marketGoods->product_raw_id; break; } } } if( !exportProductId ) return 0; //----- locate for towns that do not have the supply of the product ----// Town* townPtr; Nation* nationPtr = nation_array[nation_recno]; for( int townRecno=town_array.size() ; townRecno>0 ; townRecno-- ) { if( town_array.is_deleted(townRecno) ) continue; townPtr = town_array[townRecno]; if( townPtr->population < 20 - (10*nationPtr->pref_trading_tendency/100) ) // 10 to 20 as the minimum population for considering trade continue; if( townPtr->has_product_supply[exportProductId-1] ) // if the town already has the supply of product, return now continue; if( townPtr->region_id != region_id ) continue; if( townPtr->no_neighbor_space ) // if there is no space in the neighbor area for building a new firm. continue; if( m.points_distance( center_x, center_y, townPtr->center_x, center_y ) > MAX_WORLD_X_LOC/4 ) // don't consider if it is too far away continue; if( townPtr->town_recno && nationPtr->get_relation_status(townPtr->town_recno) < RELATION_FRIENDLY ) // only build markets to friendly nation's town { continue; } //-----------------------------------------// if( townPtr->nation_recno ) { //--- if it's a nation town, only export if we have trade treaty with it ---// if( !nationPtr->get_relation(townPtr->nation_recno)->trade_treaty ) continue; } else { //--- if it's an independent town, only export if the resistance is low ---// if( townPtr->resistance(nation_recno) > INDEPENDENT_LINK_RESISTANCE ) continue; } } return 0; }
//----------- Begin of function Nation::find_best_place_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 - >0 id. of the firm to be built // 0 if the place to be built is a town // <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. // [short] distance - the distance between the given place and // new place. // // return: <int> 1 - succeed, 0 - fail // int Nation::find_best_place_loc(short buildFirmId, short refXLoc, short refYLoc, short& resultXLoc, short& resultYLoc, short distance) { #define IDEAL_INTER_PLACE_SPACE 3 if (distance == 0) distance = IDEAL_INTER_PLACE_SPACE; 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(); int effectiveDis; //-----------------------------------------// if( locPtr->is_firm() ) { originFirmRecno = locPtr->firm_recno(); firmPtr = firm_array[originFirmRecno]; centerX = firmPtr->center_x; centerY = firmPtr->center_y; effectiveDis = world.effective_distance(buildFirmId, firmPtr->firm_id); // 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; effectiveDis = world.effective_distance(buildFirmId, 0); } else err_here(); refX1 = centerX - effectiveDis; refY1 = centerY - effectiveDis; refX2 = centerX + effectiveDis; refY2 = centerY + effectiveDis; //------------------------------------------------------// int placeLocWidth, placeLocHeight; if( buildFirmId ) { placeLocWidth = firm_res[buildFirmId]->loc_width; placeLocHeight = firm_res[buildFirmId]->loc_height; } else { placeLocWidth = STD_TOWN_LOC_WIDTH; placeLocHeight = STD_TOWN_LOC_HEIGHT; } refX1 -= placeLocWidth/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 -= placeLocHeight/2; refX1 = max(0, refX1); refY1 = max(0, refY1); refX2 = min(MAX_WORLD_X_LOC-1, refX2); refY2 = min(MAX_WORLD_Y_LOC-1, refY2); //-------- 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 ) { effectiveDis = world.effective_distance(firmPtr->firm_id, buildFirmId); refBX1 = firmPtr->center_x - effectiveDis; refBY1 = firmPtr->center_y - effectiveDis; refBX2 = firmPtr->center_x + effectiveDis; refBY2 = firmPtr->center_y + effectiveDis; weightAdd = 40; } } refCX1 = firmPtr->loc_x1-distance ; // add negative weights on space around this firm refCY1 = firmPtr->loc_y1-distance ; // so to prevent firms from building right next to the firm refCX2 = firmPtr->loc_x2+distance ; // and leave some space for walking path. refCY2 = firmPtr->loc_y2+distance ; weightReduce = 20; } //------- if there is a town on the location ------// else if( locPtr->is_town() ) { townPtr = town_array[locPtr->town_recno()]; effectiveDis = world.effective_distance(0, buildFirmId); refBX1 = townPtr->center_x - effectiveDis; refBY1 = townPtr->center_y - effectiveDis; refBX2 = townPtr->center_x + effectiveDis; refBY2 = townPtr->center_y + effectiveDis; 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-(int)townPtr->resistance(nation_recno) ) / 100; else // more friendly nations get higher weights { int relationStatus = get_relation_status(townPtr->nation_recno); if( relationStatus >= RELATION_NEUTRAL ) weightAdd = weightAdd * (relationStatus-RELATION_NEUTRAL+1) / 4; } } refCX1 = townPtr->loc_x1-distance ; // add negative weights on space around this firm refCY1 = townPtr->loc_y1-distance ; // so to prevent firms from building right next to the firm refCX2 = townPtr->loc_x2+distance ; // and leave some space for walking path. refCY2 = townPtr->loc_y2+distance ; 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 -= placeLocWidth-1; // do not scan beyond the border refY2 -= placeLocHeight-1; for( yLoc=refY1 ; yLoc<=refY2 ; yLoc++ ) { for( xLoc=refX1 ; xLoc<=refX2 ; xLoc++ ) { if( world.get_region_id(xLoc, yLoc) != buildRegionId ) continue; if( buildFirmId ) { if( !world.can_build_firm(xLoc, yLoc, buildFirmId) ) continue; } else { if( !world.can_build_town(xLoc, yLoc) ) continue; } //---- calculate the average weight of a firm area ----// int totalWeight=0; refMatrixPtr = refMatrix + (yLoc-refY1)*refWidth + (xLoc-refX1); for( int yCount=0 ; yCount<placeLocHeight ; yCount++ ) { for( int xCount=0 ; xCount<placeLocWidth ; xCount++ ) { totalWeight += *refMatrixPtr++; } refMatrixPtr += refWidth-placeLocWidth; } //------- compare the weights --------// thisWeight = totalWeight / (placeLocWidth*placeLocHeight); if( thisWeight > bestWeight ) { bestWeight = thisWeight; resultXLoc = xLoc; resultYLoc = yLoc; } } } //------ release the refective matrix -----// mem_del( refMatrix ); return resultXLoc >= 0; }