AI Constants questions

Please post here for questions and discussion about scenario design and general game modding.

Moderator: Gil R.

Post Reply
wwhitman
Posts: 8
Joined: Thu Mar 06, 2008 5:56 pm

AI Constants questions

Post by wwhitman »

Hi all. I've been actively modding the game since I got it, and I think giving us players the ability to mod through text files is one of the best decisions the designers made. I have logged dozens of tweaks to unit and building costs, terrain def and move values, gun power and range, weapon availability, camp reinforcement rates, etc., and to see those changes affect the game is a thrill. I've re-started my first campaign three separate times (so far...) because I wanted to go back and re-play the early turns with different rules in place.

But, I've hit a roadblock. Playing as the Confederate States, I can't figure out how to make the Union AI stop attacking me when his troops are outnumbered or suffering from low disposition. I'm betting this is something I can influence using the following three values in the ACWConstants.txt file:

AI Ideal Odds
AI Refuse Odds
AI Reluctance Scale

....but I don't know which way to move the numbers, how sensitive they are, and what else might (unintentionally) be thrown out of whack. I'm not asking for any state secrets, I just want to keep Rosecrans from leading 20,000 troops against 30,000 troops that just whipped him the prior turn. Is there a level to set these numbers that will cause the AI to wait a few turns and build up before seeking battle?
Conny D
Posts: 52
Joined: Tue Nov 27, 2007 2:34 am

RE: AI Constants questions

Post by Conny D »

Strange theres no response here since other questions are picked up instantly. I also think the ai should in some way be forbidden to lead single divisions against whole armies, what it does at times.
User avatar
ericbabe
Posts: 11848
Joined: Wed Mar 23, 2005 3:57 am
Contact:

RE: AI Constants questions

Post by ericbabe »

The AI is forbidden from moving divisions into provinces with ungarrisoned enemy units, but it does break this rule from time to time for reasons that aren't easy to explain pertaining to the way the AI engine is structured.  I have considered making the rule that uncontainered brigades simple fail to move into any province containing ungarrisoned enemy units.

Here's the core of the target-evaluation routine that explains the use of these parameters.  This is only called for certain military groups, not lone divisions.  The "power" of a group is determined by most all the relevant factors, including disposition, weapon, etc.


int TAI::a3_Get_Value_Of_Target_To_Piece(TAITarget *pT, GAMEPIECE pPiece)
{
    if (pPiece->GetPlayerId()!=AIPlayer ||
         pPiece->GetContainer() ||
         !pPiece->IsMilitary())
        return 0;

    int    value = 0;
    float attackPower = (float) a4_Calc_Piece_Power(pPiece)+(3*pT->maxPowerCanDeploy/4);
    if (AIPlayer==CSA)                // V1.9.10    csa more cautious on the attack
        attackPower = (float) a4_Calc_Piece_Power(pPiece)+(pT->maxPowerCanDeploy/5);
    float defendPower = (float) pT->enemyPower-(pT->powerDeployed);
    float idealOdds   = (float) AI_IdealOddsx100/100.0f;        //1.6f;
    float refuseOdds  = (float) AI_RefuseOddsx100/100.0f;    //.7f;

    int distance = a4_Can_Piece_Reach_Target(pPiece, pT->hProv);
    if (distance==0)
        return 0;

// MAKE SURE TARGET IS IN THE SAME THEATER AS THIS PIECE
    TProvince* pPieceProv = PTGame->Prov(pPiece->GetProvince());
    TProvince* pTargProv  = PTGame->Prov(pT->hProv);

    if (pTargProv->AIReluctance[AIPlayer])
    {
        defendPower *= (1.0f + (float) pTargProv->AIReluctance[AIPlayer]*AI_ReluctanceScalex100/100.0f);
    }

// DON'T ENTER THEATER -1 PROVINCES WITH BIG FORCES
    if (pPieceProv && pTargProv &&
        pTargProv->Theater==-1 &&
        attackPower>10000)
    {
        return 0;
    }

// CSA player doesn't like to invade
    if (pPiece->GetPlayerId()==CSA)
    {
        if (pTargProv->hVeryOriginalNation!=CSA && bCSADontInvadeThisTurn)
            return 0;
    }
// USA player doesn't want to invade    V1.10.6
    if (pPiece->GetPlayerId()==USA)
    {
        if (pTargProv->hVeryOriginalNation!=USA && bUSADontInvadeThisTurn)
            return 0;
    }

// WON'T INVADE IF NOT ADJACENT
    if (!PTGame->Info_CalcIsProvinceAdjacentToPlayer(pT->hProv, pPiece->GetPlayerId()))
        return 0;


// check power of defender
    if (defendPower)
    {
        float attackRatio = attackPower / defendPower;
        if (attackRatio > 2.0f*idealOdds)        // V1.9.1 don't value overkill
        {
            value = pT->value/2;    // V1.9.8
        }
        else if (attackRatio > idealOdds)
        {
            value = (int) (idealOdds*pT->value);
        }
&nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; else if (attackRatio < refuseOdds)
&nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; {
&nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; value = 0;
&nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; }
&nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; else
&nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; {
&nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; value = (int) (attackRatio*pT->value);
&nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; }
&nbsp;&nbsp;&nbsp; }
&nbsp;&nbsp;&nbsp; else
&nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; value = pT->value;
// value of targets in home terr worth more
&nbsp;&nbsp;&nbsp; if (PTGame->PTProvMap->location(pT->hProv)->GetPlayerId()==AIPlayer)
&nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; value *= 2;
// value of mississippi river
&nbsp;&nbsp;&nbsp; switch(pT->hProv)
&nbsp;&nbsp;&nbsp; {
&nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; case 235:
&nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; case 201:
&nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; case 199:
&nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; case 204:
&nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; case 206:
&nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; case 207:
&nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; case 208:
&nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; case 209:
&nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; value *= 3;
&nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; break;
&nbsp;&nbsp;&nbsp; }

//&nbsp;&nbsp;&nbsp; V1.9.1 theaters now scale value
&nbsp;&nbsp;&nbsp; if (pPieceProv && pTargProv &&
&nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; pTargProv->Theater>0 &&
&nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; pPieceProv->Theater>0 &&
&nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; pPieceProv->Theater!=pTargProv->Theater)
&nbsp;&nbsp;&nbsp; {
&nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; value = value*AI_OutOfTheaterMultiplierOnValuex100;
&nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; value /= 100;
&nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; if (distance>4)&nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; // V1.9.11
&nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; value = 0;
&nbsp;&nbsp;&nbsp; }
// V1.9.5 AI lock some milgroups to particular theaters
&nbsp;&nbsp;&nbsp; if (strcmp(pPiece->GetName(), "Army_Potomac_Left")==0 ||
&nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; strcmp(pPiece->GetName(), "Army_Potomac_Center")==0 ||
&nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; strcmp(pPiece->GetName(), "Army_Potomac_Right")==0 ||
&nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; strcmp(pPiece->GetName(), "Dept._N._Virginia")==0 ||
&nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; strcmp(pPiece->GetName(), "Dist._of_the_Potomac")==0 ||
&nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; strcmp(pPiece->GetName(), "Valley_District")==0 ||
&nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; strcmp(pPiece->GetName(), "Dept_of_NE_Virginia")==0 ||
&nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; strcmp(pPiece->GetName(), "Army_of_the_Potomac")==0 ||
&nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; strcmp(pPiece->GetName(), "Army_of_the_Peninsula")==0 ||
&nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; strcmp(pPiece->GetName(), "Aquia_District")==0)
&nbsp;&nbsp;&nbsp; {
&nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; if (pTargProv->Theater!=5)
&nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; value = 0;
&nbsp;&nbsp;&nbsp; }

// V1.9.1 does destination have enemy siegeworks?
&nbsp;&nbsp;&nbsp; GAMEPIECE pEnemySiege = PTGame->Info_FindEnemy_UnitType_Here(pT->hProv, AIPlayer, TMasterPiece::siegeworks);
&nbsp;&nbsp;&nbsp; if (pEnemySiege)
&nbsp;&nbsp;&nbsp; {
&nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; value *= AI_EnemySiegex100;
&nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; value /= 100;
&nbsp;&nbsp;&nbsp; }
&nbsp;&nbsp;&nbsp;

// value decreases by distance
&nbsp;&nbsp;&nbsp; switch(distance)
&nbsp;&nbsp;&nbsp; {
&nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; case 1:&nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; value *= AI_ValueDistance0; break;
&nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; case 2:&nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; value *= AI_ValueDistance1; break;
&nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; case 3:&nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; value *= AI_ValueDistance2; break;
&nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; case 4:&nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; value *= AI_ValueDistance3; break;
&nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; case 5:&nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; value *= AI_ValueDistance4; break;
&nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; case 6:&nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; value *= AI_ValueDistance5; break;
&nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; case 7:&nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; value *= AI_ValueDistance6; break;
&nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; case 8:&nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; value *= AI_ValueDistance7; break;
&nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; case 9:&nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; value *= AI_ValueDistance8; break;
&nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; case 10:&nbsp;&nbsp;&nbsp; value *= AI_ValueDistance9; break;
&nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; default:&nbsp;&nbsp;&nbsp; value *= AI_ValueDistanceGr9; break;
&nbsp;&nbsp;&nbsp; }
&nbsp;&nbsp;&nbsp; return value;
}




Image
User avatar
morganbj
Posts: 3472
Joined: Sun Aug 12, 2007 1:36 am
Location: Mosquito Bite, Texas

RE: AI Constants questions

Post by morganbj »

Gee, that might have been a little more than you wanted ...&nbsp;&nbsp;
&nbsp;
&nbsp;
Occasionally, and randomly, problems and solutions collide. The probability of these collisions is inversely related to the number of committees working on the solutions. -- Me.
Post Reply

Return to “Mods and Scenarios”