//----------------------------------------------------------------------
void AIController::processAgentPathOrders( ArenaMap& currentMap, Orders& tentativeOrders )
{
	EnterCriticalSection( &m_agentsCS );
	
	for( auto agentIter = m_agents.begin(); agentIter != m_agents.end(); ++agentIter )
	{
		Agent* currAgent = agentIter->second;
		if( !currAgent->currentPath.empty() )
		{
			if( currAgent->entityType == ENTITY_TYPE_WORKER && currAgent->specialStatus != ENTITY_SPECIAL_STATUS_CARRYING_FOOD )
			{
				currentMap.getMapTile( currAgent->currentTargetLoc.x, currAgent->currentTargetLoc.y ).isClaimed = true;
			}
			tentativeOrders.AddOrder( currAgent->entityID, currAgent->currentPath.back(), true );
		}
	}

	LeaveCriticalSection( &m_agentsCS );
}
//----------------------------------------------------------------------
void AIController::handleQueenOrders( Agent* queen, ArenaMap& currentMap, const ObservedEntities& entities, Orders& tentativeOrders )
{
	if( ( m_turnNumber > 0 && m_turnNumber % TURN_INTERVAL_QUEEN_MOVES_ON == 0 ) || m_numWorkersThatCouldntFindFoodThisFrame >= NUM_WORKERS_IDLE_BEFORE_QUEEN_MOVES || m_currentNumWorkers <= 0 )
	{
		if( m_currentNumWorkers <= 0 && m_currentUpkeep*TURN_UPKEEP_TOLERANCE + m_arenaInfo.nutrientCostToBirthWorker )
			tentativeOrders.AddOrder( queen->entityID, ORDER_CREATE_WORKER );
		else if( queen->currentPath.empty() && !queen->waitingForPath )
		{
			queen->currentTargetLoc = getLocationForQueenToGoTo( currentMap );
			m_agentsRequestingPaths.push( queen->entityID );
			queen->waitingForPath = true;
		}
	}
	else 
	{
		switch( m_currentQueenState )
		{
		case GATHER_RESOURCES:
			if( m_currentNutrients > m_currentUpkeep*TURN_UPKEEP_TOLERANCE + m_arenaInfo.nutrientCostToBirthWorker )//&& !m_spawnedWorkerLastFrame )
			{
				tentativeOrders.AddOrder( queen->entityID, ORDER_CREATE_WORKER );
				m_spawnedWorkerLastFrame = true;
			}
			else if( m_currentNutrients > m_currentUpkeep*TURN_UPKEEP_TOLERANCE + m_arenaInfo.nutrientCostToBirthScout )
			{
				if( m_currentNumScouts < MAX_NUM_SCOUTS )
					tentativeOrders.AddOrder( queen->entityID, ORDER_CREATE_SCOUT );
				m_spawnedWorkerLastFrame = false;	
			}
			break;
		case DEFEND:
			if( m_currentNutrients > m_currentUpkeep*TURN_UPKEEP_TOLERANCE + m_arenaInfo.nutrientCostToBirthSoldier && m_currentNumWorkers >= MIN_NUM_WORKERS )
			{
				tentativeOrders.AddOrder( queen->entityID, ORDER_CREATE_SOLDIER, true );
				m_spawnedWorkerLastFrame = false;	
			}
			else if( m_currentNumScouts < MAX_NUM_SCOUTS )
				tentativeOrders.AddOrder( queen->entityID, ORDER_CREATE_SCOUT );
			else if( m_currentNutrients > m_currentUpkeep*TURN_UPKEEP_TOLERANCE + m_arenaInfo.nutrientCostToBirthWorker && !m_spawnedWorkerLastFrame && !currentMap.hasNoMoreResources() )
			{
				tentativeOrders.AddOrder( queen->entityID, ORDER_CREATE_WORKER );
				m_spawnedWorkerLastFrame = true;
			}
			m_spawnedWorkerLastFrame = false;
			break;
		case ATTACK:
			if( m_currentNutrients > m_currentUpkeep*TURN_UPKEEP_TOLERANCE + m_arenaInfo.nutrientCostToBirthSoldier && ( currentMap.hasNoMoreResources() || m_currentNumWorkers >= MIN_NUM_WORKERS ) )
			{
				tentativeOrders.AddOrder( queen->entityID, ORDER_CREATE_SOLDIER );
				m_spawnedWorkerLastFrame = false;	
			}
			else if( m_currentNutrients > m_currentUpkeep*TURN_UPKEEP_TOLERANCE + m_arenaInfo.nutrientCostToBirthWorker && !m_spawnedWorkerLastFrame && !currentMap.hasNoMoreResources() )
			{
				tentativeOrders.AddOrder( queen->entityID, ORDER_CREATE_WORKER );
				m_spawnedWorkerLastFrame = true;
			}
			else
				m_spawnedWorkerLastFrame = false;
			break;		
		}
	}
}
//----------------------------------------------------------------------
void AIController::handleWorkerOrders( Agent* worker, ArenaMap& currentMap, const ObservedEntities& entities, Orders& tentativeOrders )
{
	if( m_currentQueenState == ATTACK && currentMap.hasNoMoreResources() && worker->specialStatus != ENTITY_SPECIAL_STATUS_CARRYING_FOOD )
	{
		tentativeOrders.AddOrder( worker->entityID, ORDER_SUICIDE );
	}
	else
	{
		if( worker->currentPath.empty() && !worker->waitingForPath )
		{
			if( worker->pos == m_queen->pos && worker->specialStatus == ENTITY_SPECIAL_STATUS_CARRYING_FOOD )
			{
				tentativeOrders.AddOrder( worker->entityID, ORDER_DROP_FOOD, true );
				--m_numWorkersWithFood;
				worker->currentTargetAgentID = -1;
			}
			else if( worker->pos == worker->currentTargetLoc && currentMap.getMapTileType( worker->pos.x, worker->pos.y ) == ARENA_SQUARE_TYPE_FOOD )
			{
				tentativeOrders.AddOrder( worker->entityID, ORDER_TAKE_FOOD, true );
				m_agentsRequestingPaths.push( worker->entityID );
				worker->currentTargetLoc = m_queen->pos;
				worker->currentTargetAgentID = m_queen->entityID;
				worker->waitingForPath = true;
				currentMap.getMapTile( worker->pos.x, worker->pos.y ).isClaimed = false;
			}	
			else if( worker->specialStatus != ENTITY_SPECIAL_STATUS_CARRYING_FOOD )
			{
				int x, y;
				if( currentMap.getClosestNutrient( m_arenaInfo.visibilityRangeQueen*QUEEN_RANGE_FACTOR, m_queen->pos, x, y ) )
				{
					m_agentsRequestingPaths.push( worker->entityID );
					worker->currentTargetLoc = TileCoords( x, y );
					worker->currentTargetAgentID = -1;
					worker->waitingForPath = true;
					currentMap.getMapTile( x, y ).isClaimed = true;
				}
				else
				{
					++m_numWorkersThatCouldntFindFoodThisFrame;
					if( m_numWorkersThatCouldntFindFoodThisFrame >= NUM_WORKERS_IDLE_BEFORE_QUEEN_MOVES )
					{
						worker->currentTargetAgentID = m_queen->entityID;
					}
					else
					{
						worker->currentTargetAgentID = -1;
						worker->currentTargetLoc = currentMap.getRandomLocationInArea( worker->pos, m_arenaInfo.visibilityRangeQueen*QUEEN_RANGE_FACTOR );
					}
					m_agentsRequestingPaths.push( worker->entityID );
					worker->waitingForPath = true;
				}
			}
			else
			{
				worker->currentTargetAgentID =  m_queen->entityID;
				m_agentsRequestingPaths.push( worker->entityID );
				worker->waitingForPath = true;
			}
		}
		else if( currentMap.getMapTileType( worker->currentTargetLoc.x, worker->currentTargetLoc.y ) != ARENA_SQUARE_TYPE_FOOD && worker->specialStatus != ENTITY_SPECIAL_STATUS_CARRYING_FOOD )
		{
			int x, y;
			if( currentMap.getClosestNutrient( m_arenaInfo.visibilityRangeQueen*QUEEN_RANGE_FACTOR, m_queen->pos, x, y ) )
			{
				m_agentsRequestingPaths.push( worker->entityID );
				worker->currentTargetLoc = TileCoords( x, y );
				worker->currentTargetAgentID = -1;
				worker->waitingForPath = true;
				currentMap.getMapTile( x, y ).isClaimed = true;
			}
		}
		else if( currentMap.hasNewMapInfo() && !worker->waitingForPath && !validPath( currentMap, worker->pos, worker->currentPath ) )
		{
			m_agentsRequestingPaths.push( worker->entityID );
			worker->waitingForPath = true;
		}
	}
}
//----------------------------------------------------------------------
void AIController::handleAgentReports( ArenaMap& currentMap, const AgentReports& agentReports, const ObservedEntities& entities, Orders& tentativeOrders )
{
	EnterCriticalSection( &m_agentsCS );
	for( int i = 0; i < agentReports.m_numberAgentReports; ++i )
	{
		Agent*& currentAgent = m_agents[ agentReports.m_agentReports[i].m_entityID ];
		//Indicates this is a new entity
		if( currentAgent == nullptr )
		{
			createNewAgent( currentAgent, agentReports.m_agentReports[i] );
		}
		else
		{
			if( agentReports.m_agentReports[i].m_reportCode == REPORT_WAS_KILLED_IN_COMBAT || 
				agentReports.m_agentReports[i].m_reportCode == REPORT_STARVED_TO_DEATH ||
				agentReports.m_agentReports[i].m_reportCode == REPORT_SUICIDE_SUCCESSFUL )
			{
				handleAgentDied( currentAgent, currentMap, agentReports.m_agentReports[i] );
				m_currentQueenState = DEFEND;
			}
			else
			{
				if( agentReports.m_agentReports[i].m_agentType == ENTITY_TYPE_WORKER && agentReports.m_agentReports[i].m_reportCode == REPORT_TAKE_SUCCESSFUL )
					++m_numWorkersWithFood;

				currentAgent->pos.x = agentReports.m_agentReports[i].m_newPositionX;
				currentAgent->pos.y = agentReports.m_agentReports[i].m_newPositionY;
				currentAgent->specialStatus = agentReports.m_agentReports[i].m_specialStatus;
				if( agentReports.m_agentReports[i].m_reportCode == REPORT_MOVE_SUCCESSFUL )
				{
					if( !currentAgent->currentPath.empty() )
						currentAgent->currentPath.pop_back();
					if( currentAgent->currentPath.empty() )
						currentAgent->waitingForPath = false;
				}
				else if( agentReports.m_agentReports[i].m_reportCode == REPORT_HOLD_SUCCESSFUL )
				{
					if( currentAgent == m_queen && !m_queen->currentPath.empty() && m_queen->currentPath.back() == ORDER_HOLD )
						currentAgent->currentPath.pop_back();
					if( currentAgent->currentPath.empty() )
						currentAgent->waitingForPath = false;
				}
				else if( agentReports.m_agentReports[i].m_reportCode == REPORT_ERROR_BLOCKED_BY_ROCK )
				{
					currentAgent->currentPath.clear();
					m_agentsRequestingPaths.push( currentAgent->entityID );
				}
				else if( currentAgent->entityType == ENTITY_TYPE_QUEEN )
				{
					if( agentReports.m_agentReports[i].m_reportCode == REPORT_QUEEN_WAS_FED )
						currentMap.getMapTile( m_queen->pos.x, m_queen->pos.y ).isClaimed = false;	
					else if( agentReports.m_agentReports[i].m_reportCode == REPORT_CREATE_SUCCESSFUL && m_currentQueenState == DEFEND )
					{
						m_currentQueenState = GATHER_RESOURCES;
					}
					else if( agentReports.m_agentReports[i].m_reportCode == REPORT_QUEEN_WAS_ASSAULTED && m_queen->currentPath.empty() )
					{
						tentativeOrders.AddOrder( m_queen->entityID, ORDER_CREATE_SOLDIER, true );
					}
				}
			}
		}
	}
	LeaveCriticalSection( &m_agentsCS );
}
Beispiel #5
0
//-----------------------------------------------------------------------------------------------
void BeginWork()
{
//	DebuggerPrintf( "[%d] WORKER THREAD: BeginWork() called.\n", g_playerID );

	while( !g_isQuitting )
	{
		EnterCriticalSection( &cs_ordersAndResults );
		bool areTentativeOrdersEmpty = g_tentativeOrders.m_numberOfOrders == 0;
		bool areResultsEmpty = g_resultsForPreviousOrders.m_numberAgentReports == 0;
		LeaveCriticalSection( &cs_ordersAndResults );

		bool readyToStartGeneratingNewOrders = areTentativeOrdersEmpty && !areResultsEmpty;
		if( !readyToStartGeneratingNewOrders )
		{
			EnterCriticalSection( &cs_ordersAndResults );
			g_readyToDispatchOrders = true;
			LeaveCriticalSection( &cs_ordersAndResults );
			Sleep( 0 );
		}
		else
		{
            EnterCriticalSection( &cs_ordersAndResults );
			Orders tempOrdersWhileWeDoLotsOfWork;
			int numOrdersToGive = (int) g_resultsForPreviousOrders.m_numberAgentReports;

			for( int resultIndex = 0; resultIndex < numOrdersToGive; ++ resultIndex )
			{
                const AgentReport& result = g_resultsForPreviousOrders.m_agentReports[ resultIndex ];
                int antID = result.m_entityID;
                OrderCode orderCode = ORDER_HOLD;

                if( result.m_specialStatus == ENTITY_SPECIAL_STATUS_DEAD )
                {
                    if( result.m_reportCode == REPORT_WAS_KILLED_IN_COMBAT )
                        ++GameInfo::g_myQueen->numberOfAntsLostInCombat;

                    if( g_myAnts.find( antID ) != g_myAnts.end() )
                    {
                        g_myAnts[antID]->ProcessDeath();
                        --gameInfo.numOfAntsPerType[(int)result.m_agentType];
                        delete g_myAnts[antID];
                        g_myAnts.erase( antID );
                        continue;
                    }
                }

                else
                {
                    if( result.m_reportCode == REPORT_WAS_CREATED )
                    {
                        switch( result.m_agentType )
                        {
                        case ENTITY_TYPE_SCOUT: 
                            g_myAnts[antID] = new AntScout( result );
                            break;

                        case ENTITY_TYPE_SOLDIER:
                            g_myAnts[antID] = new AntSoldier( result );
                            break;

                        case ENTITY_TYPE_QUEEN: 
                            gameInfo.g_myQueen = new AntQueen( result );
                            g_myAnts[antID] = gameInfo.g_myQueen;
                            break;

                        case ENTITY_TYPE_WORKER: 
                            g_myAnts[antID] = new AntWorker( result );
                            break;
                        }
                        ++gameInfo.numOfAntsPerType[(int)result.m_agentType];
                    }

                    if( gameInfo.myAnts.find( antID ) != gameInfo.myAnts.end() )
                        orderCode = g_myAnts[antID]->update( result );

                    tempOrdersWhileWeDoLotsOfWork.AddOrder( antID, orderCode, true );
                }
			}
            
            //float timeSpent = GetAbsoluteTimeSeconds() - gameInfo.secondsSinceLastFetchOrders;
            //DebuggerPrintf( "Milliseconds Spent: %f\n", timeSpent * 1000 );

            /*if( GameInfo::totalAStarRequests )
            {
                DebuggerPrintf( "Average Milliseconds Spent: %f\n", ( GameInfo::totalTimeSpentRequestingAStarPaths / GameInfo::totalAStarRequests ) * 1000 );
            }*/
            GameInfo::bSoldierSacrificed = false;
            g_readyToDispatchOrders = true;
			g_tentativeOrders = tempOrdersWhileWeDoLotsOfWork;
            g_resultsForPreviousOrders.m_numberAgentReports = 0;
			LeaveCriticalSection( &cs_ordersAndResults );
		}
	}
}