Page 10 of 13

Re: AI mod suggestions.

Posted: Sun Nov 26, 2017 10:57 am
by TommyCD1
Not until I have a computer at home again. Everything to do with this game is currently on hiatus until my 'personal issues' are in order. :W

Needs AI-writing instructions

Posted: Sat Dec 30, 2017 11:05 pm
by Secg
So far I've received feedback from a Croatian player that my Heroic Mod campaign is as hard as intended 8) . Still, the gamer thought that my GB missions were still unmodded, even though I'm sure that I'd modded both the missions' layouts as well as AI. Perhaps because the AIs were not aggressive enough.

All that said, I appreciate any input to help me write more bellicose AI which will give me barely any breathing space at all :ROCK: .

How to make Sarge & other Heroes defend the base

Posted: Tue Jan 16, 2018 2:26 pm
by Secg
First, I'd like to to thank you TommyCD1 for figuring how to use Sarge & other Heroes to attack, retreat when seriously wounded, & get healed, & attack again. Still, I am working on a Defensive AI & I hope TommyCD1 would tell me how to code so that my Sarge & Heroes only ward off enemies when their base is under my attack.

Re: New personalities for the AI.

Posted: Tue Jan 16, 2018 3:29 pm
by TommyCD1
Currently, as far to my knowledge, there is no way to get anyone to defend the base, since the AI fails to recognize that it is under attack at all. It only searches for what it defines as 'undefended clusters' (don't ask me wtf that means or how it determines that) and your only hope is to have it assume that whoever is attacking is also worth fighting. Sorry.
idk

AI offensive-defensive confusion

Posted: Tue Jan 16, 2018 5:34 pm
by Secg
Thanks for the reply. Guess I have to use my Grenadiers & my Sarge to deal with overly aggressive enemy Sarges who pay my base visits from time to time then.

Still, will you have a look at my Defense Sarge script?

Code: Select all

  // Defense Sarge script
  CreateScript("personality.tens.offense.scorch")
  {
    InitialState("Recruit");

    CreateVarString("%.types", "");
    //CreateVarFloat("%.range", 100.0);
    CreateVarInteger("%.acceptInsufficient", 0);
    //CreateVarFloat("%.danger", 0.2);
    CreateVarInteger("%.cluster.target");
    CreateVarString("%.base");
    CreateVarString("%.tag", "");

    State("Recruit")
    {
      Action("Recruit", "TypeBase")
      {
        Config("%.types");
        Location()
        {
          Base("Base", "%.base");
        }
        Range("%.range");
        AcceptInsufficient("%.acceptInsufficient");
        Base("%.base");
      }
      Conditions()
      {
        Condition("ObjectiveCondition")
        {
          Condition("Timer")
          {
            Time(10);  // Wait 10 seconds. If we don't have a sarge then abort.
          }
          Transition()
          {
            GoToState("HaveSarge");
          }
        }
      }
    }

    // Do I have a Sarge?
    State("HaveSarge")
    {
      Settings()
      {
        Setting("Tag")
        {
          Tag("%.tag");
          Append(1);
        }
      }
      Conditions()
      {
        Condition("Count")
        {
          Amount(0);
          Operator(">");
          Transition()
          {
            GoToState("Find");
          }
        }
        Condition("Count")
        {
          Amount(0);
          Operator("<=");
          Transition()
          {
            GoToState("Abort");
          }
        }
      }
    }
    
    State("Find");
    CreateVarInteger("%.cluster");
    CreateVarString("%.base");
    State("Find")
    {
      Action("ApplyRule")
      {
        Rule("FindProtectBase");
        ArmourClass("structure");
        Var("%.cluster");
        Base("%.base");
      }
      Conditions()
      {
        Condition("Count")
        {
          Amount(0);
          Operator("==");
          Transition()
          {
            GoToState("Wait");
          }
        }
        Status("Completed")
        {
          GoToState("Move");
        }
        Status("Failed")
        {
          GoToState("Wait");
        }
      }
    }
    
     State("Move")
    {
      Action("Move")
      {
        Attack(1);
        Location()
        {
          Base("VarCluster", "%.cluster");
        }
      }
      Conditions()
      {
        Condition("ObjectiveCondition")
        {
          Condition("Timer")
          {
            Time(10);
          }
          Transition()
          {
            GoToState("Find");
          }
        }
      }
    }

    State("Wait")
    {
      Conditions()
      {
        Condition("Count")
        {
          Amount(1);
          Operator(">");
          Transition()
          {
            GoToState("Find");
          }
        }
      }
    }
  }
 
Still, I notice that in many cases, the AI attacks my base with their defensive units :? & leave their offensive units at home most of the time (despite my coded timers Light Infantry must attack after 3 minutes, heavy infantry 5, vehicles 9, choppers 10, & dumdum 12). At best they only use Light & Heavy Infantry, rarely if at all use Vehicles, yet sometimes send 9 choppers after 30 minutes :( instead of sending 3 choppers every 10 minutes.

Re: AI offensive-defensive confusion

Posted: Tue Jan 16, 2018 8:02 pm
by TommyCD1
Well, with what code I have here, I can see that your code has a few errors...
  • Code: Select all

        //CreateVarFloat("%.range", 100.0);
    Your line that defines the %.range in which Sarge is located from the base has been commented out. This wouldn't be a problem, however you still have the code itself calling upon the variable integer when attempting to recruit Sarge,

    Code: Select all

          Action("Recruit", "TypeBase")
          {
            Config("%.types");
            Location()
            {
              Base("Base", "%.base");
            }
            Range("%.range");
            AcceptInsufficient("%.acceptInsufficient");
            Base("%.base");
          }
    and since it hasn't been defined and therefore does not exist, the game will crash.
  • Code: Select all

        State("Find");
        CreateVarInteger("%.cluster");
        CreateVarString("%.base");
        State("Find")
        {
    The 'Find' state is defined twice; the first time without and parameters, and the second time with said parameters (by parameters I mean what comes between { and } when a line does not terminate with a semicolon). This will also crash the game.
  • Code: Select all

        CreateVarString("%.types", "");
        //CreateVarFloat("%.range", 100.0);
        CreateVarInteger("%.acceptInsufficient", 0);
        //CreateVarFloat("%.danger", 0.2);
        CreateVarInteger("%.cluster.target");
        CreateVarString("%.base");
        CreateVarString("%.tag", "");
    
        State("Find");
        CreateVarInteger("%.cluster");
        CreateVarString("%.base");
        State("Find")
    Your %.base string has also been defined twice in this same code.
  • If this is the entirety of your code, then you are lacking an Abort state, which is called upon if the Recruit state fails to find a suitable unit to add (in this case Sarge I presume).

    Code: Select all

            Condition("Count")
            {
              Amount(0);
              Operator("<=");
              Transition()
              {
                GoToState("Abort");
              }
            }
  • Finally the name of your script is "personality.tens.offense.scorch", which would not cause errors, but it may cause conflicting data if you use it simultaneously with my tens.x AI. This crashes the game. To fix this, simply change 'tens' or the entire name to whatever you like.
Also, the AI attacking with their defense units is because their defensive units are not actually defensive at all. Even though their script uses the action rule 'FindProtectBase' they still actively search out enemy units during this phase, not their own buildings to defend. I assume that naming the different squads offensive and defensive was merely done to distinguish them during programming, as the AI has no true defensive actions outside building towers, (or mines... :tehe: ). But your issue with the AI not using their squads on schedule as intended is very common. A fix that can sort of be used to resolved this to an extent is to make sure that you properly have a threshold set for the amount units required before a squad is considered 'complete' and can be moved out. This is typically defined in the 'Wait' state. Another small fix is to simply have the AI build more buildings, while also keeping at least one of their building ungraded, so as to alleviate some of the queue traffic for high requirement units. This is actually seen to an extent in the default Pandemic AI with their two barracks.
Unfortunately, however, the biggest cause of this issue is simply the AI's lack of a suitable target. The plain fact is that the AI is extremely picky in determining if a cluster is worthy of their intervention, especially when it involves human opponents. You could maybe try increasing the danger variable (defined in the mod.cfg file) or try to daisy-chain your 'Find' state (or multiple find states) to loop back into itself when it fails, rather than heading to a 'Wait' state. This can sometimes help, and I use this method in my tens.x AI, if you'd like to see how that AI plays...

All in all, I hope the novel I just wrote didn't come off too """constructive""" and you get some help out of it! ;)

Re: AI mod suggestions.

Posted: Wed Jan 17, 2018 1:31 pm
by Secg
Thanks for the very detailed Reply. So I guess there is no way to make an AI's Sarge only defends his base when under attack at all.

& I think I've figured out how to prevent the AI from using their Defensive Units to attack. Let's say the Default AI. It's Orderer for Defensive Infantry has 2 grunts & 2 grenadiers

Code: Select all

  // Defense infantry
  CreateBase::Orderer("personality.default.defense.infantry")
  {
    Manifest("Level")
    {
      Script("defense.infantry");
      Types()
      {
        Add("army.unit.grunt",2);
        Add("army.unit.grenadier",2);
      }
      CanBuild(1);
      Random(1);
      //NoBeyondWeighting(1);
    }
  }
& its defensive vehicles has 1 halftrack, 1 tank, & 1 dumdum

Code: Select all

  // Defense vehicles
  CreateBase::Orderer("personality.default.defense.vehicles")
  {
    Manifest("Level")
    {
      Script("defense.land");
      Types()
      {
        Add("army.unit.halftrack", 1);
        Add("army.unit.tank", 1);
        Add("army.unit.medicjeep", 1);
      }
      CanBuild(1);
      Random(1);
      //NoBeyondWeighting(1);
    }
  }
Both of these Orderers use the same script ("defense.land") which is, in mod.cfg, linked

Code: Select all

  ExecuteScript("defense.land", "personality.default.defense.land")
  {
    Op("%.base", "=", "base");
  }
linked to "personality.default.defense.land" in personality_default_scripts.cfg

That 'defensive' script has a ("Wait") state, which dictates that the squad must not move out unless it has more than five units:

Code: Select all

    State("Wait")
    {
      Conditions()
      {
        Condition("Count")
        {
          Amount(5);
          Operator(">");
          Transition()
          {
            GoToState("Find");
          }
        }
      }
    }
  }
Since the 'defensive' infantry Orderers only has 4, & 'defensive' Vehicles 3 (fewer than 5); theoretically each squad would not move out. However, as I was writing my Great Battles AIs, I increase the number of 'defensive' infantry & as a result, both squads move out, or sometimes only the vehicles move out (imagine my face when a Tank & Dumdum shows up at my mostly undefended base with only Sarge & a few grunts & nadiers).

Need Tommy CD1's help to fix glitch

Posted: Fri Feb 16, 2018 12:33 am
by Secg
I'd like to give credits to you ;) for creating the "tens" AI, which is very offensively-oriented, & I based my new gb AIs on tens.

Still, I encounter this glitch when playing. Sometimes the AI creates an offensive squad within its base which does NOT move out; yet the AI keeps creating similar squads until its whole base is full of over 60-70 infantry units or 20-30 tanks & choppers :o .; which I have to bomb to destroy.

I'll put here all my .cfg fils for one AI "gbblitz," which glitches the most often for you to examine & suggest improvements (note: I'd made sure that the AI won't rebuild lost buildings)

mod.cfg

Code: Select all

///////////////////////////////////////////////////////////////////////////////
//
// Pandemic Studios
//
// AI Personality Configuration - Great Battles
//

// Don't load this for Multi
Random(0);

// Add files to the AI configuration stream
Files("AI")
{
  Add("personality_gbblitz_scripts.cfg");
  Add("personality_gbblitz_orderers_units.cfg");
  Add("personality_gbblitz_bases.cfg");
}

StartActionAll()
{
  // Create the base
  AddBase("base", "personality.gbblitz.army");

  // Add all units currently on the team
  AssignBaseConstructors("base");
  AssignBaseUnits("base");
  
  // Set up an apropriate unit limit
  SetUnitLimit(100);

  // Start up the scripts
  ExecuteScript("offense.land", "personality.gbblitz.offense.land")
  {
    Op("%.danger", "=", 0.65);
    Op("%.base", "=", "base");
  }
  ExecuteScript("offense.advland", "personality.gbblitz.offense.advland")
  {
    Op("%.danger", "=", 0.6);
    Op("%.base", "=", "base");
  }
  ExecuteScript("offense.vehicles", "personality.gbblitz.offense.vehicles")
  {
    Op("%.danger", "=", 0.5);
    Op("%.base", "=", "base");
  }
  ExecuteScript("offense.air", "personality.gbblitz.offense.air")
  {
    Op("%.danger", "=", 0.3);
    Op("%.base", "=", "base");
  }
  ExecuteScript("offense.dumdum", "personality.gbblitz.offense.dumdum")
  {
    Op("%.danger", "=", 0.2);
    Op("%.base", "=", "base");
  }
  ExecuteScript("defense.infantry", "personality.gbblitz.defense.infantry")
  {
    Op("%.base", "=", "base");
  }
  ExecuteScript("defense.vehicles", "personality.gbblitz.defense.vehicles")
  {
    Op("%.base", "=", "base");
  }
}
personality_gbblitz_bases.cfg

Code: Select all

///////////////////////////////////////////////////////////////////////////////
//
// Pandemic Studios
//
// AI Personality Configuration (Bases)
//

Strategic()
{
  CreateBase("personality.gbblitz.army")
  {
    InitialState("initial");

    State("initial")
    {
      Orderers()
      {
        // now, get some rudimentary base defense and upgrade
        Add("personality.gbblitz.defense.infantry", 1, 10, 0);
        Add("personality.gbblitz.offense.infantry", 1, 30, 0);
        // start cranking out some defensive vehicles and a barracks upgrade
        Add("personality.gbblitz.defense.vehicles", 1, 40, 0);
        // Now that we've got a barracks2, lets crank out an attack force
        Add("personality.gbblitz.offense.advinfantry", 1, 50, 0);
        // vehicles are used in attacks too, y'know!
        Add("personality.gbblitz.offense.vehicles", 1, 80, 0);
        // go hammer and tongs cranking out units
        Add("personality.gbblitz.offense.air", 1, 90, 0);
        Add("personality.gbblitz.offense.dumdum", 1, 100, 0);
        // and the final touches...
        Add("personality.gbblitz.baserepair", 1, 100, 0);
      }
    }
	
    // here until I figure out what to do with them.
    // should provide base defense
    State("underattack")
    {
      Orderers()
      {
        // Defense
        //Add("personality.gbblitz.defense.infantry", 1, 110, 0);
        //Add("personality.gbblitz.defense.vehicles", 1, 120, 0);
      }
    }
	
  }
}
personality_gbblitz_orderers_units.cfg

Code: Select all

///////////////////////////////////////////////////////////////////////////////
//
// Pandemic Studios
//
// AI Personality Configuration (Orderers)
//

Strategic()
{
  // Offense infantry
  CreateBase::Orderer("personality.gbblitz.offense.infantry")
  {
    Manifest("OrdererLevel")
    {
      Script("offense.land");
      Types()
      {
        Add("army.unit.tank",2);
      }
      CanBuild(1);
      Random(1);
      //NoBeyondWeighting(1);
    }
  }

  // Offense infantry
  CreateBase::Orderer("personality.gbblitz.offense.advinfantry")
  {
    Manifest("OrdererLevel")
    {
      Script("offense.advland");
      Types()
      {
        Add("army.unit.chopper",2);
      }
      CanBuild(1);
      Random(1);
      //NoBeyondWeighting(1);
    }
  }


  // Offense vehicles
  CreateBase::Orderer("personality.gbblitz.offense.vehicles")
  {
    Manifest("OrdererLevel")
    {
      Script("offense.vehicles");
      Types()
      {
        Add("army.unit.tank", 4);
      }
      CanBuild(1);
      Random(1);
      //NoBeyondWeighting(1);
    }
  }
  
   // Offense air
  CreateBase::Orderer("personality.gbblitz.offense.air")
  {
    Manifest("OrdererLevel")
    {
      Script("offense.air");
      Types()
      {
        Add("army.unit.chopper", 3);
      }
      CanBuild(1);
      Random(1);
    }
  }

  // Dumdum
  CreateBase::Orderer("personality.gbblitz.offense.dumdum")
  {
    Manifest("OrdererLevel")
    {
      Script("offense.dumdum");
      Types()
      {
        Add("army.unit.dumdum", 2);
      }
      CanBuild(1);
      Random(1);
      //NoBeyondWeighting(1);
    }
  }

  // Defense infantry
  CreateBase::Orderer("personality.gbblitz.defense.infantry")
  {
    Manifest("Level")
    {
      Script("defense.infantry");
      Types()
      {
        Add("army.unit.machinegunner",3);
        Add("army.unit.bazooka",2);
        Add("army.unit.sniper",1);
      }
      CanBuild(1);
      Random(1);
      //NoBeyondWeighting(1);
    }
  }

  // Defense vehicles
  CreateBase::Orderer("personality.gbblitz.defense.vehicles")
  {
    Manifest("Level")
    {
      Script("defense.vehicles");
      Types()
      {
        Add("army.unit.chopper",1);
        Add("army.unit.tank",1);
      }
      CanBuild(1);
      Random(1);
      //NoBeyondWeighting(1);
    }
  }

  // Base repair
  CreateBase::Orderer("personality.gbblitz.baserepair")
  {
    Manifest("Level")
    {
      Types()
      {
        Add("army.unit.medicjeep");
      }
      CanBuild(1);
      Random(1);
    }
  }
}
personality_gbblitz_scripts.cfg

Code: Select all

///////////////////////////////////////////////////////////////////////////////
//
// Pandemic Studios
//
// AI Personality Configuration (Scripts)
//

Strategic()
{
  // Land offense script
  CreateScript("personality.gbblitz.offense.land")
  {
    InitialState("Start");

    CreateVarFloat("%.danger", 0.2);
    CreateVarInteger("%.cluster.target");
    CreateVarString("%.base");

    State("Start")
    {
      Conditions()
      {
        Condition("ObjectiveCondition")
        {
          Condition("Timer")
          {
            Time(270);
          }
          Transition()
          {
            GoToState("Wait");
          }
        }
      }
    }

    State("Find")
    {
      Action("ApplyRule")
      {
        Rule("FindUndefendedCluster");
        Var("%.cluster.target");
        DangerRatio("%.danger");
      }
      Conditions()
      {
        Condition("Count")
        {
          Amount(1);
          Operator("<=");
          Transition()
          {
            GoToState("Wait");
          }
        }
        Status("Completed")
        {
          GoToState("Move");
        }
        Status("Failed")
        {
          GoToState("Seek");
        }
      }
    }

    State("Seek")
    {
      Action("ApplyRule")
      {
        Rule("FindProtectBase");
        ArmourClass("structure");
        Var("%.cluster.target");
        Base("%.base");
      }
      Conditions()
      {
        Condition("Count")
        {
          Amount(1);
          Operator("<=");
          Transition()
          {
            GoToState("Wait");
          }
        }
        Status("Completed")
        {
          GoToState("Move");
        }
        Status("Failed")
        {
          GoToState("Find");
        }
      }
    }

    State("Move")
    {
      Action("Move")
      {
        Attack(1);
        Location()
        {
          Base("VarCluster", "%.cluster.target");
        }
      }
      Conditions()
      {
        Condition("Count")
        {
          Amount(0);
          Operator("==");
          Transition()
          {
            GoToState("Wait");
          }
        }
        Condition("ObjectiveCondition")
        {
          Condition("Timer")
          {
            Time(30);
          }
          Transition()
          {
            GoToState("Find");
          }
        }
        Status("Completed")
        {
          GoToState("Find");
        }
      }
    }

    State("Wait")
    {
      Conditions()
      {
        Condition("Count")
        {
          Amount(2);
          Operator(">=");
          Transition()
          {
            GoToState("Find");
          }
        }
      }
    }
  }

/////////////////////////////////////////////////////////////////
// Adv Land
//
  CreateScript("personality.gbblitz.offense.advland")
  {
    InitialState("Start");

    CreateVarFloat("%.danger", 0.2);
    CreateVarInteger("%.cluster.target");
    CreateVarString("%.base");

    State("Start")
    {
      Conditions()
      {
        Condition("ObjectiveCondition")
        {
          Condition("Timer")
          {
            Time(360);
          }
          Transition()
          {
            GoToState("Wait");
          }
        }
      }
    }

    State("Find")
    {
      Action("ApplyRule")
      {
        Rule("FindUndefendedCluster");
        Var("%.cluster.target");
        DangerRatio("%.danger");
      }
      Conditions()
      {
        Condition("Count")
        {
          Amount(1);
          Operator("<=");
          Transition()
          {
            GoToState("Wait");
          }
        }
        Status("Completed")
        {
          GoToState("Move");
        }
        Status("Failed")
        {
          GoToState("Seek");
        }
      }
    }

    State("Seek")
    {
      Action("ApplyRule")
      {
        Rule("FindProtectBase");
        ArmourClass("structure");
        Var("%.cluster.target");
        Base("%.base");
      }
      Conditions()
      {
        Condition("Count")
        {
          Amount(1);
          Operator("<=");
          Transition()
          {
            GoToState("Wait");
          }
        }
        Status("Completed")
        {
          GoToState("Move");
        }
        Status("Failed")
        {
          GoToState("Find");
        }
      }
    }

    State("Move")
    {
      Action("Move")
      {
        Attack(1);
        Location()
        {
          Base("VarCluster", "%.cluster.target");
        }
      }
      Conditions()
      {
        Condition("Count")
        {
          Amount(0);
          Operator("==");
          Transition()
          {
            GoToState("Wait");
          }
        }
        Condition("ObjectiveCondition")
        {
          Condition("Timer")
          {
            Time(30);
          }
          Transition()
          {
            GoToState("Find");
          }
        }
        Status("Completed")
        {
          GoToState("Find");
        }
      }
    }

    State("Wait")
    {
      Conditions()
      {
        Condition("Count")
        {
          Amount(2);
          Operator(">=");
          Transition()
          {
            GoToState("Find");
          }
        }
      }
    }
  }


/////////////////////////////////////////////////////////////////
// Adv Land
//
  CreateScript("personality.gbblitz.offense.vehicles")
  {
    InitialState("Start");

    CreateVarFloat("%.danger", 0.2);
    CreateVarInteger("%.cluster.target");
    CreateVarString("%.base");

    State("Start")
    {
      Conditions()
      {
        Condition("ObjectiveCondition")
        {
          Condition("Timer")
          {
            Time(540);
          }
          Transition()
          {
            GoToState("Wait");
          }
        }
      }
    }

    State("Find")
    {
      Action("ApplyRule")
      {
        Rule("FindUndefendedCluster");
        Var("%.cluster.target");
        DangerRatio("%.danger");
      }
      Conditions()
      {
        Condition("Count")
        {
          Amount(3);
          Operator("<=");
          Transition()
          {
            GoToState("Wait");
          }
        }
        Status("Completed")
        {
          GoToState("Move");
        }
        Status("Failed")
        {
          GoToState("Seek");
        }
      }
    }

    State("Seek")
    {
      Action("ApplyRule")
      {
        Rule("FindProtectBase");
        ArmourClass("structure");
        Var("%.cluster.target");
        Base("%.base");
      }
      Conditions()
      {
        Condition("Count")
        {
          Amount(3);
          Operator("<=");
          Transition()
          {
            GoToState("Wait");
          }
        }
        Status("Completed")
        {
          GoToState("Move");
        }
        Status("Failed")
        {
          GoToState("Find");
        }
      }
    }

    State("Move")
    {
      Action("Move")
      {
        Attack(1);
        Location()
        {
          Base("VarCluster", "%.cluster.target");
        }
      }
      Conditions()
      {
        Condition("Count")
        {
          Amount(2);
          Operator("<=");
          Transition()
          {
            GoToState("Wait");
          }
        }
        Condition("ObjectiveCondition")
        {
          Condition("Timer")
          {
            Time(30);
          }
          Transition()
          {
            GoToState("Find");
          }
        }
        Status("Completed")
        {
          GoToState("Find");
        }
      }
    }

    State("Wait")
    {
      Conditions()
      {
        Condition("Count")
        {
          Amount(4);
          Operator(">=");
          Transition()
          {
            GoToState("Find");
          }
        }
      }
    }
  }

  // Dumdum script

  CreateScript("personality.gbblitz.offense.dumdum")
  {
    InitialState("Start");

    CreateVarFloat("%.danger", 0.2);
    CreateVarInteger("%.cluster.target");
    CreateVarString("%.base");

    State("Start")
    {
      Conditions()
      {
        Condition("ObjectiveCondition")
        {
          Condition("Timer")
          {
            Time(720);
          }
          Transition()
          {
            GoToState("Wait");
          }
        }
      }
    }

    State("Find")
    {
      Action("ApplyRule")
      {
        Rule("FindUndefendedCluster");
        Var("%.cluster.target");
        DangerRatio("%.danger");
      }
      Conditions()
      {
        Condition("Count")
        {
          Amount(1);
          Operator("<=");
          Transition()
          {
            GoToState("Wait");
          }
        }
        Status("Completed")
        {
          GoToState("Move");
        }
        Status("Failed")
        {
          GoToState("Seek");
        }
      }
    }

    State("Seek")
    {
      Action("ApplyRule")
      {
        Rule("FindProtectBase");
        ArmourClass("structure");
        Var("%.cluster.target");
        Base("%.base");
      }
      Conditions()
      {
        Condition("Count")
        {
          Amount(1);
          Operator("<=");
          Transition()
          {
            GoToState("Wait");
          }
        }
        Status("Completed")
        {
          GoToState("Move");
        }
        Status("Failed")
        {
          GoToState("Find");
        }
      }
    }

    State("Move")
    {
      Action("Move")
      {
        Attack(1);
        Location()
        {
          Base("VarCluster", "%.cluster.target");
        }
      }
      Conditions()
      {
        Condition("Count")
        {
          Amount(1);
          Operator("<=");
          Transition()
          {
            GoToState("Wait");
          }
        }
        Condition("ObjectiveCondition")
        {
          Condition("Timer")
          {
            Time(30);
          }
          Transition()
          {
            GoToState("Find");
          }
        }
        Status("Completed")
        {
          GoToState("Find");
        }
      }
    }

    State("Wait")
    {
      Conditions()
      {
        Condition("Count")
        {
          Amount(2);
          Operator(">=");
          Transition()
          {
            GoToState("Find");
          }
        }
      }
    }
  }

  // Air offense script
  CreateScript("personality.gbblitz.offense.air")
  {
    InitialState("Start");

    CreateVarFloat("%.danger", 0.2);
    CreateVarInteger("%.cluster.target");
    CreateVarString("%.base");

    State("Start")
    {
      Conditions()
      {
        Condition("ObjectiveCondition")
        {
          Condition("Timer")
          {
            Time(180);
          }
          Transition()
          {
            GoToState("Wait");
          }
        }
      }
    }

    State("Find")
    {
      Action("ApplyRule")
      {
        Rule("FindUndefendedCluster");
        Var("%.cluster.target");
        DangerRatio("%.danger");
      }
      Conditions()
      {
        Condition("Count")
        {
          Amount(2);
          Operator("<=");
          Transition()
          {
            GoToState("Wait");
          }
        }
        Status("Completed")
        {
          GoToState("Move");
        }
        Status("Failed")
        {
          GoToState("Seek");
        }
      }
    }

    State("Seek")
    {
      Action("ApplyRule")
      {
        Rule("FindProtectBase");
        ArmourClass("structure");
        Var("%.cluster.target");
        Base("%.base");
      }
      Conditions()
      {
        Condition("Count")
        {
          Amount(2);
          Operator("<=");
          Transition()
          {
            GoToState("Wait");
          }
        }
        Status("Completed")
        {
          GoToState("Move");
        }
        Status("Failed")
        {
          GoToState("Find");
        }
      }
    }

    State("Move")
    {
      Action("Move")
      {
        Attack(1);
        Location()
        {
          Base("VarCluster", "%.cluster.target");
        }
      }
      Conditions()
      {
        Condition("Count")
        {
          Amount(1);
          Operator("<=");
          Transition()
          {
            GoToState("Wait");
          }
        }
        Condition("ObjectiveCondition")
        {
          Condition("Timer")
          {
            Time(30);
          }
          Transition()
          {
            GoToState("Find");
          }
        }
        Status("Completed")
        {
          GoToState("Find");
        }
      }
    }

    State("Wait")
    {
      Conditions()
      {
        Condition("Count")
        {
          Amount(3);
          Operator(">=");
          Transition()
          {
            GoToState("Find");
          }
        }
      }
    }
  }

  // Land defense script
  CreateScript("personality.gbblitz.defense.infantry")
  {
    InitialState("Find");
    CreateVarInteger("%.cluster");
    CreateVarString("%.base");
    State("Find")
    {
      Action("ApplyRule")
      {
        Rule("FindProtectBase");
        ArmourClass("structure");
        Var("%.cluster");
        Base("%.base");
      }
      Conditions()
      {
        Condition("Count")
        {
          Amount(0);
          Operator("==");
          Transition()
          {
            GoToState("Wait");
          }
        }
        Status("Completed")
        {
          GoToState("Move");
        }
        Status("Failed")
        {
          GoToState("Wait");
        }
      }
    }

    State("Move")
    {
      Action("Move")
      {
        Attack(1);
        Location()
        {
          Base("VarCluster", "%.cluster");
        }
      }
      Conditions()
      {
        Condition("ObjectiveCondition")
        {
          Condition("Timer")
          {
            Time(10);
          }
          Transition()
          {
            GoToState("Find");
          }
        }
      }
    }
    State("Wait")
    {
      Conditions()
      {
        Condition("Count")
        {
          Amount(7);
          Operator(">");
          Transition()
          {
            GoToState("Find");
          }
        }
      }
    }
  }
  
  // Land defense script
  CreateScript("personality.gbblitz.defense.vehicles")
  {
    InitialState("Find");
    CreateVarInteger("%.cluster");
    CreateVarString("%.base");
    State("Find")
    {
      Action("ApplyRule")
      {
        Rule("FindProtectBase");
        ArmourClass("structure");
        Var("%.cluster");
        Base("%.base");
      }
      Conditions()
      {
        Condition("Count")
        {
          Amount(0);
          Operator("==");
          Transition()
          {
            GoToState("Wait");
          }
        }
        Status("Completed")
        {
          GoToState("Move");
        }
        Status("Failed")
        {
          GoToState("Wait");
        }
      }
    }

    State("Move")
    {
      Action("Move")
      {
        Attack(1);
        Location()
        {
          Base("VarCluster", "%.cluster");
        }
      }
      Conditions()
      {
        Condition("ObjectiveCondition")
        {
          Condition("Timer")
          {
            Time(10);
          }
          Transition()
          {
            GoToState("Find");
          }
        }
      }
    }
    State("Wait")
    {
      Conditions()
      {
        Condition("Count")
        {
          Amount(3);
          Operator(">");
          Transition()
          {
            GoToState("Find");
          }
        }
      }
    }
  }
}

Re: New personalities for the AI.

Posted: Fri Feb 16, 2018 11:19 am
by TommyCD1
Well, I don't see any issues in any of your .cfg files. Keep in mind that when a computer player is fighting a human player, they are extremely picky about what they consider to be worthy of an assault. Usually a player tends to build their base very compactly, in order to allow the most amount of buildings, with no towers, and this can usually cause the AI to feel that can be overlooked. If you pit an AI against itself, or against another AI, then you will usually see them begin to attack each other, as they build to their liking of each other. Also, with the AI you have provided, there's no logical way they would amass the 70 unit armies you have described above. Is this your only AI?

Basically, the only real advice I can give here is to test AI's not against yourself, but against each other. idk

Bugged GB AIs

Posted: Fri Feb 16, 2018 1:11 pm
by Secg
That is not the only AI one I have. I've written 10 GB AIs to make the GB missions harder for my mod. The gbblitz AI is the one who bugs the most. Just imagine my face when I invade its base & found that it has over 20 tanks or over 20 choppers :o which should've attacked my base from time to time instead of staying. :?

Still, I think you are right in this respect, I build my base too compactly & because the gbblitz AI is forbidden by me to make Minesweeper, I only lay Thumbtacks & some AA guns & yet never build any tower or pillbox in the direction facing its base (Waterway War's NW Tan-Base)l that's why it decides my base is not worth attacking.