Exemplo n.º 1
0
//------- Begin of function FirmHarbor::think_build_firm -----------//
//
void FirmHarbor::think_build_firm()
{
	Nation* ownNation = nation_array[nation_recno];

	if( ownNation->cash < 2000 )		// don't build if the cash is too low
		return;

	if( ownNation->true_profit_365days() < (50-ownNation->pref_use_marine)*20 )		//	-1000 to +1000
		return;

	//----- think about building markets ------//

	if( ownNation->pref_trading_tendency >= 60 )
	{
		if( ai_build_firm(FIRM_MARKET) )
			return;
	}

	//----- think about building camps ------//

	if( ownNation->pref_military_development/2 +
		 (linked_firm_count + ownNation->ai_ship_count + ship_count) * 10 +
		 ownNation->total_jobless_population*2 > 150 )
	{
		ai_build_firm(FIRM_CAMP);
	}
}
Exemplo n.º 2
0
int Unit::think_normal_monster_action()
{
	if( home_camp_firm_recno )
		return 0;

	//--- if the entire nation does not have any lairs ----//

	Nation* nationPtr = nation_array[nation_recno];

	if( nationPtr->is_monster() &&
		 ( nationPtr->ai_camp_count==0 ||

		//---- If there are more units than the existing lairs can hold ---//

			nationPtr->total_camp_unit_space(0) <= nationPtr->total_unit_count ) )
	{
		return ai_build_firm();
	}

	//---- try to assign units to existing lairs -----//

	if( leader_unit_recno &&
		 unit_array[leader_unit_recno]->is_visible() )		// if the unit is led by a commander, let the commander makes the decision. If the leader has been assigned to a firm, don't consider it as a leader anymore
	{
		return 0;
	}

	return think_assign_soldier_to_camp();
}
Exemplo n.º 3
0
int Unit::think_normal_human_action()
{
	if( home_camp_firm_recno )
		return 0;

	//-- if we also don't have any existing camps in this region --//

	Nation* nationPtr = nation_array[nation_recno];

	if( nationPtr->ai_camp_count==0 ||
		 nationPtr->total_camp_unit_space(0) <= nationPtr->total_unit_count )	// If there are more units than the existing forts can hold
	{
		if( ai_build_firm() )
			return 1;
	}

	//--- the following are actions that are only performed if the unit is not led by a commander ---//

	if( leader_unit_recno &&
		 unit_array[leader_unit_recno]->is_visible() )		// if the unit is led by a commander, let the commander makes the decision. If the leader has been assigned to a firm, don't consider it as a leader anymore
	{
		return 0;
	}

	err_when( !race_id );
	err_when( !nation_recno );

	//--- if this is a military unit, think about assigning it to a camp or fort ---//

	if( !is_civilian() )
	{
		if( think_assign_soldier_to_camp() )
			return 1;
	}
	else
	{
		if( think_assign_human_to_town() )
			return 1;
	}

	return 0;
}
Exemplo n.º 4
0
//------- Begin of function Nation::process_action --------//
//
// [int] priorityActionRecno - if this is given, this specific action will
//								 	    be processed first. Otherwise it will process
//							  		    actions in the array in a sequential order.
//
// [int] processActionMode   - if this is given, only message of this type
//										 will be processed and all messages in the queued of this 
//										 type will be processed. 
//
// Note: priorityActionRecno and processActionMode couldn't be used at
//		   the same time.
//
// return: <int> 1 - all messages of the specific action mode are processed or all messages are processed
//							or the priority message has been processed.
//
int Nation::process_action(int priorityActionRecno, int processActionMode)
{
	err_when( priorityActionRecno && processActionMode );

	int 			actionRecno, rc, delFlag, doneFlag=0;
	int			thisSessionProcessCount=0;		// actions processed in this call session
	ActionNode* actionNode;

	int divider = 1-config.ai_aggressiveness;		// the more nations there, the less process count
	int nationRecno = nation_recno;
	int maxSessionProcessCount = 70 / nation_array.nation_count / max(divider,1);

	for( actionRecno=1 ; actionRecno<=action_count() &&
		  (thisSessionProcessCount < maxSessionProcessCount || processActionMode) && !doneFlag ;		// if processActionMode has been specific, then all messages in the queue of this type will be processed
		  actionRecno++ )
	{
		//----- priority action ------//

		if( priorityActionRecno )
		{
			actionRecno = priorityActionRecno;
			doneFlag 	= 1;			// mark it done, so if the function "continue" to the next loop, the function will end
		}

		if( is_action_deleted(actionRecno) )
			continue;

		actionNode = get_action(actionRecno);

		//----- if only process specific action mode -----//

		if( processActionMode && actionNode->action_mode != processActionMode )
			continue;

		//--- if the AI action is about processing diplomatic message ---//

		if( actionNode->action_mode == ACTION_AI_PROCESS_TALK_MSG &&
			 processActionMode != ACTION_AI_PROCESS_TALK_MSG )
		{
			if( m.random(10) > 0 )		// 1/10 chance of processing the diplomatic messages
				continue;
		}

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

		if( actionNode->processing_instance_count == actionNode->instance_count )
		{
			//---------------------------------------------//
			//
			// If this action has been marked processing for over 6 months
			// and we still haven't received finishing notifications,
			// then there may be some accidents (or bugs) happened, and
			// we will need to delete the action.
			//
			//---------------------------------------------//

			if( info.game_date > actionNode->add_date + 30 * 6 )
			{
				del_action(actionRecno);
				actionRecno--;					// stay in this array position as the current one has been deleted, the following one replace the current one's position
			}

			continue;
		}

		err_when( actionNode->processing_instance_count > actionNode->instance_count );

		if( info.game_date < actionNode->next_retry_date && !priorityActionRecno )		// priorityAction bypass retry date checking
			continue;

		if( actionNode->retry_count==0 )		// the actionNode may still exist even when retry_count==0, waiting for processed_count to reach processing_count
			continue;

		//---- if the assigned unit has been deleted, cancel the action ----//

		if( actionNode->unit_recno && unit_array.is_deleted(actionNode->unit_recno) )
		{
			del_action(actionRecno);
			actionRecno--;					// stay in this array position as the current one has been deleted, the following one replace the current one's position
			continue;
		}

		//-- there is an unprocessing action in this waiting node --//

		switch( actionNode->action_mode )
		{
			case ACTION_AI_BUILD_FIRM:
				rc = ai_build_firm(actionNode);
				break;

			case ACTION_AI_ASSIGN_OVERSEER:
				rc = ai_assign_overseer(actionNode);
				break;

			case ACTION_AI_ASSIGN_SOLDIER:
				rc = ai_assign_soldier(actionNode);
				break;

			case ACTION_AI_ASSIGN_SPY:
				rc = ai_assign_spy(actionNode);
				break;

			case ACTION_AI_SCOUT:
				rc = ai_scout(actionNode);
				break;

			case ACTION_AI_BUILD_TOWN:
				rc = ai_build_town(actionNode);
				break;

			case ACTION_AI_SETTLE_TOWN:
				rc = ai_settle_town(actionNode);
				break;

			case ACTION_AI_PROCESS_TALK_MSG:
				rc = ai_process_talk_msg(actionNode);
				break;
/*
			case ACTION_AI_SEA_TRAVEL:
				err_here();
				rc = ai_sea_travel(actionNode);
				break;

			case ACTION_AI_SEA_TRAVEL2:
				err_here();
				rc = ai_sea_travel2(actionNode);
				break;

			case ACTION_AI_SEA_TRAVEL3:
				err_here();
				rc = ai_sea_travel3(actionNode);
				break;
*/		}

		if( nation_array.is_deleted(nationRecno) )		// diplomatic option can result in surrendering
			return 0;

		thisSessionProcessCount++;

		//------ check the return result -------//

		delFlag = 0;

		if( rc==1 )		// the action has been processed, but not sure whether it is complete or not
		{
			actionNode->processing_instance_count++;

			//---------------------------------------------------//
			// for ACTION_DYNAMIC, the action is immediately
			// deleted when processing_instance_count == instance_count.
			//---------------------------------------------------//

			if( actionNode->action_type == ACTION_DYNAMIC )
			{
				if( actionNode->processing_instance_count > actionNode->instance_count )
					delFlag = 1;
			}
		}
		else if( rc==0 )			// action failed, retry
		{
			if( actionNode->unit_recno )		// if the action is associated with a unit, delete the action if it fails as the associated the unit will do anything before the next try and the action will become invalid 
			{
				delFlag = 1;
			}
			else
			{
				actionNode->next_retry_date = info.game_date + 7;		// try again one week later

				if( --actionNode->retry_count==0 )
					delFlag = 1;

				err_when( actionNode->retry_count < 0 );
			}
		}
		else if( rc== -1 )		// action failed, remove immediately if return -1
		{
			actionNode->retry_count = 0;
			delFlag = 1;
		}

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

		if( delFlag && actionNode->processing_instance_count == actionNode->processed_instance_count )		// if processing_count > processed_count, do not remove this ActionNode, as there are some unit using this actionNode, when they finish or fail the action, processed_count will increase and processing_count will reach processed_count
		{
			del_action(actionRecno);
			actionRecno--;					// stay in this array position as the current one has been deleted, the following one replace the current one's position
		}
	}

	return actionRecno > action_count() || doneFlag;
}
Exemplo n.º 5
0
int Unit::think_assign_human_to_town()
{
	if( !is_human() )
		return 0;

	//---- look for towns to assign to -----//

	Nation* ownNation = nation_array[nation_recno];
	int  curRating, bestRating=0;
	int  hasTownInRegion=0;
	Town *townPtr, *bestTown=NULL;
	int  regionId = world.get_region_id( next_x_loc(), next_y_loc() );
	int  curXLoc = next_x_loc(), curYLoc = next_y_loc();

	for( int i=town_array.size() ; i>0 ; i-- )		// can't use ai_town_array[] because this function will be called by Unit::betray() when a unit defected to the player's kingdom
	{
		if( town_array.is_deleted(i) )
			continue;

		townPtr = town_array[i];

		if( townPtr->nation_recno != nation_recno )
			continue;

		if( townPtr->region_id != regionId )
			continue;

		if( !townPtr->can_accept_assign(sprite_recno) )
			continue;

		hasTownInRegion = 1;

		//--- only assign to towns of the same race ---//

		if( ownNation->pref_town_defense > 50 )
		{
			if( townPtr->majority_race() != race_id )
				continue;
		}

		//-------- calculate the rating ---------//

		curRating = world.distance_rating(curXLoc, curYLoc, townPtr->center_x, townPtr->center_y );
		curRating += MAX_TOWN_POPULATION - townPtr->population;

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

		if( curRating > bestRating )
		{
			bestRating = curRating;
			bestTown   = townPtr;
		}
	}

	if( bestTown )
	{
		assign(bestTown->loc_x1, bestTown->loc_y1);
		return 1;
	}

	//----- if we don't have any existing towns in this region ----//

	if( !hasTownInRegion )
	{
		//--- if region is too small don't consider this area, stay in the island forever --//

		if( region_array[regionId]->region_stat_id == 0 )
			return 0;

		//-- if we also don't have any existing camps in this region --//

		if( region_array.get_region_stat(regionId)->camp_nation_count_array[nation_recno-1]==0 )
		{
			//---- try to build one if this unit can ----//

			if( !leader_unit_recno )		// if this unit is commanded by a leader, let the leader build the camp
				ai_build_firm();
		}
		else		// if there is already a camp in this region, try to settle a new town next to the camp
		{
			ai_settle_new_town();
		}

		return 1;	// if we don't have any town in this region, return 1, so this unit won't be resigned and so it can wait for other units to set up camps and villages later ---//
	}

	return 0;
}