/*-----------------------------------------------------------------------------
    Name        : airSmartResearchRequests
    Description : Uses the technology deficit variable to determine if a new
                  research ship needs to be built
    Inputs      :
    Outputs     :
    Return      : Whether or not a new research ship has been requested at high priority
----------------------------------------------------------------------------*/
bool airSmartResearchRequests(bool *requestedResearch)
{
    if (aiCurrentAIPlayer->TechnologyDeficit > 0)
    {
        sdword totalResearch = aiCurrentAIPlayer->airNumResearchShips + aiCurrentAIPlayer->NumResearchShipsBeingBuilt;

        if ((real32)(totalResearch) < (((real32)(aiCurrentAIPlayer->TechnologyDeficit))/2.0))
        {
            if (aiuCanBuildShipType(ResearchShip,FALSE))
            {
                if (!totalResearch)
                {
                    aifResourceManRequestsShipsCB(ResearchShip, 1, REQUESTSHIPS_HIPRI);
                    *requestedResearch = TRUE;
                    return TRUE;
                }
                else
                {
                    aifResourceManRequestsShipsCB(ResearchShip, 1, 0);
                    *requestedResearch = TRUE;
                    return FALSE;
                }
            }
        }
        else
        {
            //recalculate technology deficit every time now.
            aiCurrentAIPlayer->TechnologyDeficit = 0;
        }
    }
    *requestedResearch = FALSE;
    return FALSE;
}
/*-----------------------------------------------------------------------------
    Name        : airDumbResearchRequests
    Description : Uses the Researchers to build variable to determine of a new
                  research ship needs to be built
    Inputs      :
    Outputs     :
    Return      : Whether or not a new research ship has been requested at high priority
----------------------------------------------------------------------------*/
bool airDumbResearchRequests(bool *requestedResearch)
{
    if (aiCurrentAIPlayer->ResearchersToBuild)
    {
        sdword totalResearch = aiCurrentAIPlayer->airNumResearchShips + aiCurrentAIPlayer->NumResearchShipsBeingBuilt;

        if (totalResearch < aiCurrentAIPlayer->ResearchersToBuild)
        {
            if (aiuCanBuildShipType(ResearchShip,FALSE))
            {
                if (!totalResearch)
                {
                    aifResourceManRequestsShipsCB(ResearchShip, 1, REQUESTSHIPS_HIPRI);
                    *requestedResearch = TRUE;
                    return TRUE;
                }
                else
                {
                    aifResourceManRequestsShipsCB(ResearchShip, 1, 0);
                    *requestedResearch = TRUE;
                }
            }
        }
    }
    else
    {
        //later maybe add a bonehead move variable as well to build up to 6
        aiCurrentAIPlayer->ResearchersToBuild = randyrandombetween(RANDOM_AI_PLAYER, 1, 3);
        aiplayerLog((aiIndex, "Using Dumb Research - %i Research Ships", aiCurrentAIPlayer->ResearchersToBuild));
    }
    return FALSE;
}
/*-----------------------------------------------------------------------------
    Name        : airProcessSpecialTeams
    Description : Processes any early ships to be built by the resource manager
    Inputs      :
    Outputs     :
    Return      : void
----------------------------------------------------------------------------*/
void airProcessSpecialTeams(void)
{
    if (!aiCurrentAIPlayer->airNumResearchShips)
    {
        if (aiuCanBuildShipType(ResearchShip,FALSE))
        {
            aifResourceManRequestsShipsCB(ResearchShip, 1, REQUESTSHIPS_HIPRI);
        }
    }
}
/*-----------------------------------------------------------------------------
    Name        : airDumbResourcerRequests
    Description : Uses the ResourcersToBuild variable to determine if a new resourcer needs to be built
    Inputs      :
    Outputs     :
    Return      : Whether or not a new resourcer has been requested at high priority
----------------------------------------------------------------------------*/
bool airDumbResourcerRequests(void)
{
    if (aiCurrentAIPlayer->ResourcersToBuild)
    {
        sdword totalRCollectors = aiCurrentAIPlayer->airNumRCollectors + aiCurrentAIPlayer->NumRCollectorsBeingBuilt;

        if (aiCurrentAIPlayer->ResourcersToBuild > totalRCollectors)
        {
            if (aiuCanBuildShipType(ResourceCollector,FALSE))
            {
                aifResourceManRequestsShipsCB(ResourceCollector, aiCurrentAIPlayer->ResourcersToBuild - totalRCollectors, REQUESTSHIPS_HIPRI);
                return TRUE;
            }
        }
    }
    else
    {
        aiCurrentAIPlayer->ResourcersToBuild = randyrandombetween(RANDOM_AI_PLAYER, (2 + (udword)aiCurrentAIPlayer->aiplayerDifficultyLevel), (4 + (udword)aiCurrentAIPlayer->aiplayerDifficultyLevel));
        aiplayerLog((aiIndex, "Using Dumb Resourcing - %i Resource Ships", aiCurrentAIPlayer->ResourcersToBuild));
    }
    return FALSE;
}
示例#5
0
sdword aimProcessFancyGetShips(AITeam *team)
{
    AITeamMove *thisMove = team->curMove;
    AIVar *doneVar;
    char label[AIVAR_LABEL_MAX_LENGTH+1];
    sdword numShipsToBuild, numShipsToGet;

    if (!thisMove->processing)
    {
        ShipType shiptype = thisMove->params.fancyGetShips.shipType;
        sdword numPointsLeftToGet = thisMove->params.fancyGetShips.numShips * ALTERNATIVE_SHIP_BASE;
        AlternativeShips *alternativeShips = &thisMove->params.fancyGetShips.alternatives;
        sdword numAlternatives = alternativeShips->numNextPicks;
        sdword i;

        doneVar = aivarCreate(aivarLabelGenerate(label));
        aivarValueSet(doneVar, 0);
        thisMove->params.fancyGetShips.doneVar = doneVar;

        // try to get as many of the requested ships as possible:
        // if any types are unavailable due to research, add check here later
        GetFromReservesShipsOfShipType(team,shiptype,ALTERNATIVE_SHIP_BASE,&numPointsLeftToGet);

        // now try alternatives
        for (i=0;i<numAlternatives;i++)
        {
            if (numPointsLeftToGet <= 0)
            {
                break;
            }

            GetFromReservesShipsOfShipType(team,alternativeShips->shipTypeNextPicks[i],alternativeShips->shipNumEquivNextPicks[i],&numPointsLeftToGet);
        }

        if (numPointsLeftToGet > 0)
        {
            // we couldn't get enough from reserves, so we have to build the rest:
            if (alternativeShips->alternativeFlags & ALTERNATIVE_RANDOM)
            {
                // randomly pick the rest

                sdword j;
                udword randomnum = ranRandom(RAN_AIPlayer) % (numAlternatives+1);
                if (randomnum == 0)
                {
                    goto buildbaseshiporfirst;
                }

                randomnum--;
                dbgAssert(randomnum < numAlternatives);
                for (i=randomnum,j=0;;)
                {
                    if (aiuCanBuildShipType(alternativeShips->shipTypeNextPicks[i],(team->teamType == ScriptTeam)))
                    {
                        // found the ship we can build.  Let's build them.
                        numShipsToGet = numPointsLeftToGet / alternativeShips->shipNumEquivNextPicks[i];
                        if (numShipsToGet == 0)
                        {
                            numShipsToGet++;
                        }

                        //determine the number of ships that unit caps will let us build
                        numShipsToBuild = aiuUnitCapCanBuildShip(aiCurrentAIPlayer, alternativeShips->shipTypeNextPicks[i], numShipsToGet);

                        //if we can build all the ships
                        if (numShipsToBuild == numShipsToGet)
                        {
                            aifTeamRequestsShipsCB(alternativeShips->shipTypeNextPicks[i],numShipsToGet,team,aivarLabelGet(doneVar),
                                                   thisMove->params.fancyGetShips.priority);
                            break;
                        }
                        //if we can only build a few
                        else if (numShipsToBuild > numShipsToGet*0.25)
                        {
                            numPointsLeftToGet = (numShipsToGet - numShipsToBuild) * alternativeShips->shipNumEquivNextPicks[i];

                            dbgAssert(numPointsLeftToGet > 0);

                            aifTeamRequestsShipsCB(alternativeShips->shipTypeNextPicks[i],numShipsToBuild,team,aivarLabelGet(doneVar),
                                                   thisMove->params.fancyGetShips.priority);
                        }
                    }

                    j++;
                    if (j >= numAlternatives)
                    {
//                        aiplayerLog((aiIndex,"Warning - couldn't build any secondary ships"));
                        goto buildbaseshiporfirst;
                    }

                    i++;
                    if (i >= numAlternatives)
                    {
                        i = 0;
                    }
                }
            }
            else
            {
buildbaseshiporfirst:
                if (aiuCanBuildShipType(shiptype,(team->teamType == ScriptTeam)))
                {
                    numShipsToGet = numPointsLeftToGet / ALTERNATIVE_SHIP_BASE;
                    if (numShipsToGet == 0)
                    {
                        numShipsToGet++;
                    }

                    //determine the number of ships that unit caps will let us build
                    numShipsToBuild = aiuUnitCapCanBuildShip(aiCurrentAIPlayer, shiptype, numShipsToGet);

                    //if we can build all the ships
                    if (numShipsToBuild == numShipsToGet)
                    {
                        aifTeamRequestsShipsCB(shiptype,numShipsToGet,team,aivarLabelGet(doneVar),thisMove->params.fancyGetShips.priority);
                    }
                    //if we can only build some
                    else if (numShipsToBuild > numShipsToGet*0.75)
                    {
                        numPointsLeftToGet = (numShipsToBuild - numShipsToGet) * ALTERNATIVE_SHIP_BASE;
                        aifTeamRequestsShipsCB(shiptype,numShipsToBuild,team,aivarLabelGet(doneVar),thisMove->params.fancyGetShips.priority);
                    }
                    else
                    {
						aivarDestroy(doneVar);	
						thisMove->params.fancyGetShips.doneVar = NULL;
						
						//postfinal: found that the fancygetships move gets stuck here,
						//			 even though the team already has all the ships,
						//			 added if and while loop
						
						// if the current team *already* has the ships we need,
						// the move is done
						if (team->shipList.selection->numShips)
						{
							if ((team->shipList.selection->ShipPtr[0]->shiptype ==
								 thisMove->params.fancyGetShips.shipType) &&
								(team->shipList.selection->numShips >=
								 thisMove->params.fancyGetShips.numShips))
							{
								return TRUE;
							}
						
							// same as above, but goes through all the alternatives
							for (i=0;i<numAlternatives;i++)
							{
								if ((team->shipList.selection->ShipPtr[0]->shiptype ==
									 alternativeShips->shipTypeNextPicks[i]) &&
									(team->shipList.selection->numShips >=
									 (thisMove->params.fancyGetShips.numShips * 10)/alternativeShips->shipNumEquivNextPicks[i]))
								{
									return TRUE;
								}
							}
						}
                        return FALSE;
                    }
                }
                else
                {
                    for (i=0;i<numAlternatives;i++)
                    {
                        if (aiuCanBuildShipType(alternativeShips->shipTypeNextPicks[i],(team->teamType == ScriptTeam)))
                        {
                            numShipsToGet = numPointsLeftToGet / alternativeShips->shipNumEquivNextPicks[i];
                            if (numShipsToGet == 0)
                            {
                                numShipsToGet++;
                            }


                            //determine the number of ships that unit caps will let us build
                            numShipsToBuild = aiuUnitCapCanBuildShip(aiCurrentAIPlayer, alternativeShips->shipTypeNextPicks[i], numShipsToGet);

                            //if we can build all the ships
                            if (numShipsToBuild == numShipsToGet)
                            {
                                aifTeamRequestsShipsCB(alternativeShips->shipTypeNextPicks[i],numShipsToGet,team,aivarLabelGet(doneVar),
                                                       thisMove->params.fancyGetShips.priority);
                                goto havebuiltbaseshiporfirst;
                            }
                            //if we can only build some
                            else if (numShipsToBuild > numShipsToGet*0.75)
                            {
                                numPointsLeftToGet = (numShipsToBuild - numShipsToGet) * ALTERNATIVE_SHIP_BASE;
                                aifTeamRequestsShipsCB(alternativeShips->shipTypeNextPicks[i],numShipsToBuild,team,aivarLabelGet(doneVar),
                                                       thisMove->params.fancyGetShips.priority);
                            }

                        }
                    }

                    // we couldn't build base ship, or any alternatives,
                    // destroy the team and try again.
                    aiplayerLog((aiIndex,"Warning - couldn't build base or secondary ship %i, deleting team", shiptype));
					aivarDestroy(doneVar);	
					thisMove->params.fancyGetShips.doneVar = NULL;
                    bitSet(team->teamFlags, AIT_DestroyTeam);
                    return TRUE;
                }
havebuiltbaseshiporfirst:;
            }
        }
        else
        {
            aivarValueSet(doneVar, TRUE);
        }

        thisMove->processing = TRUE;
    }

    // normally in a move processing function, we'd check the
    // thisMove->wait flag, but...
    //
    // always wait for the ships to be built (we could loosen this a bit later, maybe)
    // but consider what happens when the rest of the ships are actually built if we
    // leave early
    //
    // Falko's note later: leaving early is too much trouble - formations become incomplete,
    //                     the ships built after the team executes a move sit around for
    //                     an undefined period of time and the current Numbers Low
    //                     event handler gets confused
    return aivarValueGet(thisMove->params.getShips.doneVar);
}
/*-----------------------------------------------------------------------------
    Name        : airResourceManager
    Description : Manages all the resources and non-combat ships for the computer player
    Inputs      : orders - orders from the fleet manager
    Outputs     : sets resource collectors to collect resources and optimizes resource
                  controller and other non-combat ships
    Return      : requests for new ships
----------------------------------------------------------------------------*/
void airResourceManager(void)
{
    sdword cashGenerated;
    bool requestedSomething = FALSE, requestedResearch = FALSE;

    // Update continuously updated variables

    if (((aiCurrentAIPlayer->aiplayerFrameCount & UPDATE_RU_COUNT_RATE) == 0)||
        (aiCurrentAIPlayer->airEasilyAccesibleRUsInWorld == -1))
    {
        aiCurrentAIPlayer->airEasilyAccesibleRUsInWorld = NumberOfEasilyAccesibleRUs(aiCurrentAIPlayer->player);
    }

    cashGenerated = aiCurrentAIPlayer->player->resourceUnits + aiCurrentAIPlayer->NumRUsSpentOnAttman + aiCurrentAIPlayer->NumRUsSpentOnDefman + aiCurrentAIPlayer->NumRUsSpentOnScriptman;

    //determine if we should build any research ships
    if (singlePlayerGame || (!singlePlayerGame && bitTest(tpGameCreated.flag,MG_ResearchEnabled)))
    {
        if (aiuResourceFeatureEnabled(AIR_SMART_RESEARCH_SHIP_REQUESTS))
        {
            if (airSmartResearchRequests(&requestedResearch))
            {
                //a high priority request for a research ship has been entered
                return;
            }
        }
        else
        {
            if (airDumbResearchRequests(&requestedResearch))
            {
                //a high priority request for a research ship has been entered
                return;
            }
        }
    }

    //determine if we should build any resource collectors
    if ((singlePlayerGame || (!singlePlayerGame && bitTest(tpGameCreated.flag,MG_HarvestinEnabled))) &&
        (aiCurrentAIPlayer->airEasilyAccesibleRUsInWorld > MIN_WORTHWHILE_RUs))
    {
        sdword totalRCollectors = aiCurrentAIPlayer->airNumRCollectors + aiCurrentAIPlayer->NumRCollectorsBeingBuilt;

        if (aiuResourceFeatureEnabled(AIR_SMART_COLLECTOR_REQUESTS))
        {
            if (totalRCollectors < MAX_RCOLLECTORS_TO_BUILD)
            {
                if (totalRCollectors < aiCurrentAIPlayer->NumRUDockPoints*MAX_RCOLLECTORS_PER_DOCK_POINT)
                {
                    if ((totalRCollectors == 0) || (aiCurrentAIPlayer->airEasilyAccesibleRUsInWorld > (totalRCollectors+1)*RUs_PER_RCOLLECTOR))
                    {
                        // see if we have enough cash to make it worthwhile.  (The more resource collectors we
                        // already have, the more cash we want before building a new one because the Resource
                        // Manager should always be providing an increasing amount of RU's).

                        // Note that when we say cash, we mean cashGenerated
                        if ((totalRCollectors == 0) ||      // if this is our first RCollector, we always want to build one
                            (cashGenerated > BUILD_RC_CASH_TABLE_BASE + BUILD_RC_CASH_TABLE_INC * (totalRCollectors-1)))
                        {
                            if (totalRCollectors == 0)
                            {
                                if (aiuCanBuildShipType(ResourceCollector,FALSE))
                                {
                                    aifResourceManRequestsShipsCB(ResourceCollector, 1, REQUESTSHIPS_HIPRI);
                                    return;
                                }
                            }
                            else
                            {
                                if (aiuCanBuildShipType(ResourceCollector,FALSE))
                                {
                                    aifResourceManRequestsShipsCB(ResourceCollector, 1, 0);
                                    requestedSomething = TRUE;
                                }
                            }
                        }
                    }
                }
            }
        }
        else
        {
            if (airDumbResourcerRequests())
            {
                //a resource collector has been requested at high priority
                return;
            }
        }

        //determine if we should build any resource controllers
        if (aiuResourceFeatureEnabled(AIR_RESOURCE_CONTROLLER_REQUESTS) &&
            (totalRCollectors >= MIN_RCOLLECTORS_FOR_CONTROLLER))
        {
            sdword totalRControllers = aiCurrentAIPlayer->airNumRControllers + aiCurrentAIPlayer->NumRControllersBeingBuilt;
            if ((totalRControllers == 0) && (!requestedResearch))
            {
                if (aiCurrentAIPlayer->airEasilyAccesibleRUsInWorld > (MIN_WORTHWHILE_RUs_FOR_CONTROLLER * universe.numPlayers))
                {
                    if (cashGenerated > BUILD_RCONTROLLER_CASH_BASE)
                    {
                        if (aiuCanBuildShipType(ResourceController,FALSE))
                        {
                            aifResourceManRequestsShipsCB(ResourceController, 1, 0);
                            return;
                        }
                    }
                }
            }
        }
    }

    if (!requestedSomething)
    {
        //determine if we should build any AdvanceSupportFrigates
        if (aiuResourceFeatureEnabled(AIR_SUPPORT_FRIGATE_REQUESTS) &&
            ((!singlePlayerGame) && bitTest(tpGameCreated.flag, MG_FuelBurnEnabled)) )
        {
            if (cashGenerated > BUILD_ASF_CASH_BASE)
            {
                sdword totalASF = aiCurrentAIPlayer->airNumASF + aiCurrentAIPlayer->NumASFBeingBuilt;

                if ((totalASF == 0) &&
                    aitNeedStrikeSupport(randyrandombetween(RANDOM_AI_PLAYER, 10, 15)))
                {
                    if (aiuCanBuildShipType(AdvanceSupportFrigate,FALSE) &&
                        aiuUnitCapCanBuildShip(aiCurrentAIPlayer, AdvanceSupportFrigate, 1))
                    {
                        aifResourceManRequestsShipsCB(AdvanceSupportFrigate, 1, 0);
                    }
                }
            }
        }
    }

    if (aiCurrentAIPlayer->numSupportTeams)
    {
        airDivideSupportTasks();
    }

    //Distress signals only work with active guard,
    //so that feature has to be activated as well
    if (aiuResourceFeatureEnabled(AIR_RESOURCE_DISTRESS_SIGNALS))
    {
        airCheckForDistressSignals();
    }
}