Help With Functions

Started by SPmac, March 05, 2010, 10:09:35 AM

Previous topic - Next topic

SPmac

In an attempt to set up an AI, I started off by writing some functions just to test... Here they are

//==================================================================================================
// My Functions
//==================================================================================================

void Message(int player, string msg){
  int i = FixedToInt(AIGetTime());
  msg = PlayerRace(player) + " " + IntToString(player) + msg + " Time = " + IntToString(i);
  UIDisplayMessage(PlayerGroupAll(), c_messageAreaSubtitle, StringToText(msg));
}

void One(int player){
  string msg = "Func One";
  Message(player, msg);
}

void Two(int player){
  string msg = "Func Two";
  Message(player, msg);
}

void Three(int player){
  string msg = "Func Three";
  Message(player, msg);
}

The file is included in Protoss.GALAXY...

//==================================================================================================
// Protoss Melee AI
//==================================================================================================

include "TriggerLibs/Protoss0"
include "TriggerLibs/MyProtoss"

//-----------------------------------------------------------------------------------
// Counter-Attack Units
//-----------------------------------------------------------------------------------

And I call them here...

//-----------------------------------------------------------------------------------
// AIMeleeProt
//-----------------------------------------------------------------------------------

void AIMeleeProt (int player) {
  int mainState = AIState(player, e_mainState);
  if (mainState == e_mainState_Init) { ProtossInit(player); }
  One(player);
  Twoplayer);
  Three(player);
}

They work as intended as they are above, but then I decided to try to make them function for building, the game doesn't take... Here's what I was attempting to do....

//==================================================================================================
// My Functions
//==================================================================================================

void Message(int player, string msg){
  int i = FixedToInt(AIGetTime());
  msg = PlayerRace(player) + " " + IntToString(player) + msg + " Time = " + IntToString(i);
  UIDisplayMessage(PlayerGroupAll(), c_messageAreaSubtitle, StringToText(msg));
}

void One(int player){
  AIClearStock(player);

  if(AITechCount(player, c_PU_Probe, c_techCountCompleteOnly) < 8){
    AISetStock(player, 8, c_PU_Probe);
  }

  string msg = "Func One";
  Message(player, msg);
}

void Two(int player){
  AIClearStock(player);

  if(AITechCount(player, c_PU_Probe, c_techCountCompleteOnly) >= 8){
    AISetStock(player, 1, c_PB_Pylon);
    AISetStock(player, 1, c_PB_Assimilator);
    AISetGasPeonCountOverride(player, c_townMain, 3);
  }

  string msg = "Func Two";
  Message(player, msg);
}

void Three(int player){
  AIClearStock(player);

  if(AITechCount(player, c_PU_Probe, c_techCountCompleteOnly) >= 8
  && AITechCount(player, c_PB_Pylon, c_techCountCompleteOnly) >= 1
  && AITechCount(player, c_PB_Assimilator, c_techCountCompleteOnly) >= 1){
    AISetStock(player, 1, c_PB_Gateway);
    AISetStock(player, 2, c_PB_Pylon);
    AISetStock(player, 11, c_PU_Probe);
  }

  string msg = "Func Three";
  Message(player, msg);
}

I beleive I need to set a state before I can start calling stock functions, or I need to call them from another place.. I tried alot of different things, but I can't figure it out. Anyone have an explaination on setting up an entry for this kind of call. I would really appreciate any help ;)


Yuna_Q

try this, for counting units.


//native int  AIKnownUnitCount (int player, int testPlayerId, string aliasUnitType)
AIKnownUnitCount(player, player, c_PU_Probe)

SPmac

#2
The theory of this works as I need it to, but that's not exactly what I'm after..

copy and paste error... fixed below

What I'm trying to do is execute these commands, and more like these, in my own functions, (Not using [race]0 files) in order to create a non-linear or non-timebased AI. My problem right now is figuring out the correct point to start calling these functions. The last set of functions int the OP up there is where the problem lies... Where I am calling them from or how I'm calling them must be illegal, because nothing loads on startup.

but TVM for your effort, Yuna, I'll probably be using that for counting soon enough


if(AITechCount(player, c_PU_Probe, c_techCountCompleteOnly)<10{
       AISetStock(player,10, c_PU_Probe);

}
if(AITechCount(player, c_PU_Probe, c_techCountCompleteOnly)>=10{

       AISetStock
(player,1, c_PB_Pylon);
       AISetStock(player,1, c_PB_Assimilator);
       AISetGasPeonCountOverride(player, c_townMain,3);

}
if(AITechCount(player, c_PU_Probe, c_techCountCompleteOnly)>=8
&& AITechCount(player, c_PB_Pylon, c_techCountCompleteOnly)>=1
&& AITechCount(player, c_PB_Assimilator, c_techCountCompleteOnly)>=1){

      AISetStock
(player,1, c_PB_Gateway);
      AISetStock(player,2, c_PB_Pylon);
      AISetStock(player,11, c_PU_Probe);
}

imbalisk

So lets see how the AI work to see your mistakes.
The computer will give every AI a timeslot, in which the AI functions are computed. Some functions will be called like every 1 secound or less. This means, this function is called every secound (0.5sec, 0.2 sec, dont know)

void AIMeleeProt (int player) {   
    int mainState = AIState(player, e_mainState);


    if (mainState == e_mainState_Init)              { ProtossInit(player);     }


    else if (mainState == e_mainState_OpenGnd0)     { ProtossOpenGnd0(player); }
    //else if (mainState == e_mainState_OpenGnd1)     { ProtossOpenGnd1(player); }
}

you may add a TriggerDebugOutput( ... ) in ths function to see when it's called.
The state of the AI can be set via the
void AISetMainState (int player, int mainState, int mainSubState) function, this function is called within AIMeleeInit to set the state of all AIs to 1 ( = e_mainState_Init ) so that when the AIMelee[race] (int player) function is called, [race]Init(player) is called.
That means: If the AI is Protoss, the Inintial state is 1, when the AIMeleeProt(int player) is called the first time, it will call ProtossInit(player)


ProtossInit(player) chooses an opening for the Protoss:


if (AIGetGroundStartLocs(PlayerStartLocation(player)) > 0) {
state = AIDiffEnum(player, e_mainState_OpenGnd0);
}
else {
        state = AIDiffEnum(player, e_mainState_OpenAir0);
    }
    AISetMainState(player, state, e_mainSubState_Unset);

Read it like that: If there are only island start positions, choose an air unit opening( like Void Rays), else set state to e_mainState_OpenGnd0.


So, in the nex secound, AIMeleeProt is called again, now the state is not longer e_mainState_Init, it is e_mainState_OpenGnd0 (cause we are not on an island map :) ), now the function ProtossOpenGnd0 is called, there is where most of the players put their Openings :).


You may also only want the AI only make your builds and behaviour, to make this, add

void AIMeleeProt (int player) {   
        one(player)


}

Yeah, thats enough, your AI do not longer work with states. That sux, but this will work.
Why is your AI not working?




//-----------------------------------------------------------------------------------
// AIMeleeProt
//-----------------------------------------------------------------------------------

void AIMeleeProt (int player) {
  int mainState = AIState(player, e_mainState);
  if (mainState == e_mainState_Init) { ProtossInit(player); }
  One(player);
  Twoplayer);
  Three(player);
}

You call all 3 functions after each other and dont make a decision which function you want to call. So when one( ) is called, it sets stock to 8probes. Now the AI tries to have 8 probes.
Then you call two() and clear the stock. The AI is not longer trying to make probes. It tries to makes an assimimator and an pylon, but only if it has 8 probes. But you cleared the stock, it will never try to make 8 probes.


You should take a deeper look into the ProtossOpenGnd0 function to see what it does, here is a version of my opening as P:


void ProtossOpenGnd0(int player) {
    AIClearStock(player);
    AISetGasPeonCountOverride(player, c_townMain, 6);


AISetFlag(player, e_flagsScouting, false);
    AISetFlag(player, e_flagsEarlyDefScout, false);


    if(AIGetTime() > 150 - AIGetUserInt (player, 100))
    {
AISetFlag(player, e_flagsScouting, true);
    }


     // Protoss opening v3.1 by imbalisk
    AISetStock( player, 1, c_PB_Nexus );
    AISetStock( player, 9, c_PU_Probe );
    AISetStock( player, 1, c_PB_Pylon );
    AISetStock( player, 11, c_PU_Probe );
    AISetStock( player, 1, c_PB_Gateway  );
    AISetStock( player, 13, c_PU_Probe );
    AISetStock( player, 2, c_PB_Gateway  );
    AISetStock( player, 15, c_PU_Probe );
    AISetStock( player, 2, c_PB_Pylon );
    AISetStock( player, 5, c_PU_Zealot );
    AISetStock( player, 4, c_PB_Pylon );
    AISetStock( player, 1, c_PB_Assimilator );
    AISetStock( player, 1, c_PB_CyberneticsCore );
    AISetStock( player, 1, c_PR_ZealotCharge);
   
    // around 100 resources in about 2 units
    AISetStock( player, 16, c_PU_Zealot );
    AISetStock( player, 6, c_PU_Stalker );
    ProtossTechUp(player, 1);
   
if (AIEnableVeryEasyStockOpen(player, c_PU_Probe)) {
return;
}


}

Ignore the AISetStock for a moment, whats most important is the AIEnableVeryEasyStockOpen(player, c_PU_Probe), since this will call a function in MeleeNotHard.galaxy, the AIEnableVeryEasyStockOpen.
Look at this:


bool AIEnableVeryEasyStockOpen (int player, string peonType) {
    return AIEnableStockOpen(player, peonType, 350, false, e_mainState_Mid0);
}

and

static bool AIEnableStockOpen (int player, string peonType, int time, bool veryEasy, int nextState) {
    AIEnableStock(player);


    if (AIGetTime() < time) {
        return true;
    }
    AIGenericStock(player, nextState, e_mainSubState_GndA);
    return false;
}

AIEnableStock tells the AI: ok, you can start building things that are on your Stock (i.e. try to make pylons or probes), if the time (here: 350 sec, because AiEnableVeryEasyStockOpen calls this function with 350 as parameter!) is over, launch an attack, AND SET NEXT STATE to e_mainSubState_GndA.
Next time AIMeleeProt is called (it was called like 350 times and always executed ProtossOpenGnd0) it will execute ProtossMidGndA, cause the state was set to e_mainState_Mid0.
So, in order to make a working AI, either overwrite ProtossOpenGnd0 and overwrite ProtossMidGndA and so on, and also change the EnableStockOpen functions, or make an AI like the guy who wrote the protoss AI.

SPmac

thx thx alot! ;D  i'mma have to mess round w/ this later today..  I'm not concerned about the actual functionality or strategy at this point, just figuring out the flow of everything, I'll pop back if I figures out anything neat, but this helps alot thx again.

Kernel64

is the code that tells the AI to start ordering units to attack found in
      AIGenericStock(player, nextState, e_mainSubState_GndA); ?because I have this:

Quote//This is enabled as soon as AI get more than 6 lings queued
    if ( (AITechCount(player, c_ZU_Zergling, c_techCountInProgressOrBetter) >= 12) && (AITechCount(player, c_ZU_Zergling, c_techCountCompleteOnly) > 6)   ) { // && (AITechCount(player, c_ZU_Zergling, c_techCountCompleteOnly) = 24)

        AIAddStringInt(player, c_ZU_Zergling, 6);
        AIAttackWaveAddUnits (-1, 6, c_ZU_Zergling);
        AIWaveMerge(player, c_waveMain, c_waveAttack);
        AISetAttackState(player, e_attackState_Attack);
        AIResetUserData(player);
    }
in my Zerg0.galaxy at the opening state to make the AI attack.Added this in because I wanted to stay longer in the opening state and still have the AI launch an attack, setting the transition to the next state to occur after 900 seconds.

hd

Quote from: SPmac on March 05, 2010, 11:37:02 AM
The theory of this works as I need it to, but that's not exactly what I'm after..

if(AITechCount(player, c_PU_Probe, c_techCountCompleteOnly) <{

AISetStock(player, 10, c_PU_Probe);

}


if(AITechCount(player, c_PU_Probe, c_techCountCompleteOnly) >={

AISetStock(player, 1, c_PB_Pylon);

AISetStock(player, 1, c_PB_Assimilator);

AISetGasPeonCountOverride(player, c_townMain, 3);

}


if(AITechCount(player, c_PU_Probe, c_techCountCompleteOnly) >= 8

&& AITechCount(player, c_PB_Pylon, c_techCountCompleteOnly) >= 1

&& AITechCount(player, c_PB_Assimilator, c_techCountCompleteOnly) >= 1){

AISetStock(player, 1, c_PB_Gateway);

AISetStock(player, 2, c_PB_Pylon);

AISetStock(player, 11, c_PU_Probe);

}


What I'm trying to do is execute these commands, and more like these, in my own functions, (Not using [race]0 files) in order to create a non-linear or non-timebased AI. My problem right now is figuring out the correct point to start calling these functions. The last set of functions int the OP up there is where the problem lies... Where I am calling them from or how I'm calling them must be illegal, because nothing loads on startup.

but TVM for your effort;)

The reason you load the game and nothing comes up once on the map is because your IF-THEN-ELSE statements are in error.

if(AITechCount(player, c_PU_Probe, c_techCountCompleteOnly) <{

Less than what?

if(AITechCount(player, c_PU_Probe, c_techCountCompleteOnly) >={

Greater than or equal to what?


SPmac

hd: Sry, Copy/paste error, check out the OP last section that's how it's supposed to look, but thx much for the help..

also... I got things running, turns out my problem was w/ sumthing completely different...

I commented out a block using /* ..... */

I guess it is illegal to use this method of commenting...? I used line by line commenting, and poof it works... But the section about Clearing and Enabling Stock helped tons..

thx again

Aeg1s

Quote from: SPmac on March 07, 2010, 06:59:14 PM
hd: Sry, Copy/paste error, check out the OP last section that's how it's supposed to look, but thx much for the help..

also... I got things running, turns out my problem was w/ sumthing completely different...

I commented out a block using /* ..... */

I guess it is illegal to use this method of commenting...? I used line by line commenting, and poof it works... But the section about Clearing and Enabling Stock helped tons..

thx again


Yeah no /* */ style comments.