Exemple #1
0
//----- Begin of function Nation::think_build_harbor_network ----//
//
// Think about thinking a harbor network so that we have harbors
// from every region to any other regions.
//
int Nation::think_build_harbor_network()
{
	//--- only build one harbor at a time, to avoid double building ---//

	if( is_action_exist( ACTION_AI_BUILD_FIRM, FIRM_HARBOR ) )
		return 0;

	//--------------------------------------------//

	RegionStat* regionStat = region_array.region_stat_array;
	RegionPath* regionPath;

	for( int i=0 ; i<region_array.region_stat_count ; i++, regionStat++ )
	{
		//--- only build on those regions that this nation has base towns ---//

		if( !regionStat->base_town_nation_count_array[nation_recno-1] )
			continue;

		if( regionStat->harbor_nation_count_array[nation_recno-1] > 0 )		// if we already have a harbor in this region
			continue;

		err_when( regionStat->harbor_nation_count_array[nation_recno-1] > 1 );		// this shouldn't happen if the AI works properly

		//-----------------------------------------------------------------------//
		//
		// Scan thru all regions which this region can be connected to thru sea.
		// If one of them is worth our landing, then builld a harbor in this 
		// region so we can sail to that region. 
		//
		//-----------------------------------------------------------------------//

		regionPath = regionStat->reachable_region_array;

		for( int j=0 ; j<regionStat->reachable_region_count ; j++, regionPath++ )
		{
			err_when( regionPath->land_region_stat_id == i+1 );		// pointing back to its own

			//--------------------------------------//

			if( ai_harbor_count == 0 &&		// if we have already built one harbor, then we should continue to build others asa single harbor isn't useful
				 ai_should_sail_to_rating(regionPath->land_region_stat_id) <= 0 )
			{
				continue;
			}

			//--------- build a harbor now ---------//

			if( ai_build_harbor( regionStat->region_id, regionPath->sea_region_id ) )
				return 1;
		}
	}

	return 0;
}
Exemple #2
0
//--------- Begin of function Nation::ai_should_build_mine --------//
//
int Nation::ai_should_build_mine()
{
    //---- only build mines when it has enough population ----//

    if( total_jobless_population < (100-pref_economic_development)/2 )
        return 0;

    if( total_jobless_population < 16 )		// only build mine when you have enough population to support the economic chain: mine + factory + camp
        return 0;

    if( site_array.untapped_raw_count==0 )
        return 0;

    if( !can_ai_build(FIRM_MINE) )
        return 0;

    //--- don't build additional mines unless we have enough population and demand to support it ----//

    if( ai_mine_count >= 1 )
    {
        if( true_profit_365days() < 0 || total_population < 40+pref_economic_development/5 )
            return 0;
    }

    //-- if the nation is already in the process of building a new one --//

    if( is_action_exist( ACTION_AI_BUILD_FIRM, FIRM_MINE ) )
        return 0;

    //--- if the population is low, make sure existing mines are in full production before building a new one ---//

    if( total_jobless_population < 30 )
    {
        FirmMine* firmMine;

        for( int i=0 ; i<ai_mine_count ; i++ )
        {
            firmMine = firm_array[ ai_mine_array[i] ]->cast_to_FirmMine();

            err_when( !firmMine );

            if( firmMine->worker_count < MAX_WORKER )
                return 0;

            if( firmMine->linked_firm_count==0 && !firmMine->no_neighbor_space ) 	// if the firm does not have any linked firms, that means the firm is still not in full operation
                return 0;
        }
    }

    return 1;
}
Exemple #3
0
//--------- Begin of function Nation::add_action --------//
//
// <short> xLoc, yLoc		 - location of the action
// <short> refXLoc, refYLoc - reference location (optional, not all action types need this)
// <int>   actionMode		 - action mode
// <int>   actionPara		 - action parameter
// [int]	  instanceCount	 - no. of instances of this action should be carried out
//									   (default: 1)
// [int]   unitRecno			 - recno of the unit responsible for this action
//										if not given, an appropriate unit will be found.
// [int]    actionPara2		 - action para2
// [short*] groupUnitArray  - array of unit recno in the group for the action
//										the no. of units in the array is stored in instance_count
//										(default: NULL)
//
// return: <int> recno of the action added in action_array
//					  0 - if the action is not added as it is already in action_array.
//
int Nation::add_action(short xLoc, short yLoc, short refXLoc, short refYLoc,
							  int actionMode, int actionPara, int instanceCount,
							  int unitRecno, int actionPara2, short* groupUnitArray)
{
	err_when( instanceCount < 1 );

	//--- check if the action has been added already or not ---//

	if( is_action_exist(xLoc, yLoc, refXLoc, refYLoc, actionMode, actionPara, unitRecno) )
		return 0;

	//---------- queue the action ----------//

	ActionNode actionNode;

	memset( &actionNode, 0, sizeof(ActionNode) );

	actionNode.action_mode		= actionMode;			// what kind of action
	actionNode.action_para		= actionPara;			// parameter of the action
	actionNode.action_para2		= actionPara2;			// parameter of the action
	actionNode.action_x_loc		= xLoc;					// location to act to
	actionNode.action_y_loc		= yLoc;
	actionNode.ref_x_loc			= refXLoc;				// the refective location of this action make to
	actionNode.ref_y_loc			= refYLoc;
	actionNode.retry_count		= STD_ACTION_RETRY_COUNT;  // number of term to wait before discarding this action
	actionNode.instance_count 	= instanceCount;				// num of this action being processed in the waiting queue

	int immediateProcess=0;

	if( groupUnitArray )
	{
		// the no. of units in the array is stored in instance_count

		err_when( instanceCount < 1 );
		err_when( instanceCount > ActionNode::MAX_ACTION_GROUP_UNIT );

		memcpy( actionNode.group_unit_array, groupUnitArray, instanceCount * sizeof(groupUnitArray[0]) );

		immediateProcess = 1;				// have to execute this command immediately as the unit in unit_array[] may change
		actionNode.retry_count = 1;		// only try once as the unit in unit_array[] may change
	}

	if( unitRecno )
	{
		//-- this may happen when the unit is a spy and has just changed cloak --//

		if( !nation_array[unit_array[unitRecno]->true_nation_recno()]->is_ai() &&
			 !nation_array[unit_array[unitRecno]->nation_recno]->is_ai() )
		{
			return 0;
		}

		//-------------------------------------//

		actionNode.unit_recno = unitRecno;

		err_when( actionMode == ACTION_AI_ASSIGN_OVERSEER &&		// an overseer must be a military unit
					 unit_array[unitRecno]->is_civilian() );

		if( unit_array[unitRecno]->is_visible() )
		{
			immediateProcess = 1;				// have to execute this command immediately as the unit in unit_array[] may change
			actionNode.retry_count = 1;		// only try once as the unit in unit_array[] may change
		}
		else		//--- the unit is still being trained ---//
		{
			err_here();
			// actionNode.next_retry_date = info.game_date + TOTAL_TRAIN_DAYS + 1;
		}
	}

	//-------- set action type ---------//

	actionNode.action_type = ACTION_FIXED;		// default action type

	//------- link into action_array --------//

	return add_action( &actionNode, immediateProcess );
}
Exemple #4
0
//--------- 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;
	int		effectiveDis = world.effective_distance(FIRM_MINE,0);

	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<=effectiveDis))
			{
				//------ 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<=effectiveDis)
						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;
}