Ejemplo n.º 1
0
//----- 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
	}
}
Ejemplo n.º 2
0
//------- 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);
}
Ejemplo n.º 3
0
//------- 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;
}
Ejemplo n.º 4
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;
}