Week 9
Intro to AI - Doing Stupid Stuff Since '97
You ever wonder why the AI always starts with much more stuff than you do? Because it sucks at playing OP2. If you were to write a simple AI that started with a default LoS setup and fought you, 1-on-1, in a fair fight, it would lose. Wouldn't even be much of a challenge, really. But I'll do my best to help you write a somewhat decent AI. Ready? Let's start with the basics: setting up groups, building its base and mining ore.
AI GroupsFor the AI to function at all, you need to organize its units into specialized groups for construction, repairing, mining ore, (re)building mines, attacking, defending, etc. Here are some important functions common to all unit groups:
[code]// Manipulating the group itself
Disable(); // Disables the group (I'm assuming this prevents it from doing anything or being rebuilt, but I don't know for sure)
Enable(); // Enables the group (Only needed if previously disabled)
IsInitialized(); // No idea, though I'd guess it checks if you've actually created the group/specified what type of group it should be (see below)
Destroy(); // Destroys the group. OP2 can no longer reference this group. The units in the group are freed up and can be put in another group now
// Initializing the group (note: I'll explain what each type of group does below)
CreateBuildingGroup(Player[Owner]); // Initializes this group as a building group
CreateMiningGroup(Player[Owner]): // Initializes this group as a mining group
CreateFightGroup(Player[Owner]): // Initializes this group as a fight group
// Note that each group MUST be one of these three types. There is no "generic" group type.
// Manipulating the units in the group
TakeUnit(Unit Handle); // Takes the specified unit and adds it to the group
TakeAllUnits(Unit Group); // Takes all units in the specified group and adds them to this group
SetLights(0 = off, 1 = on); // Turn on/off lights for all units in the group
SetTargCount(Unit Type, Cargo, Amount); // Used to tell a Vehicle Factory how many units of type X this group needs
ClearTargCount(); // Erases any data set by SetTargCount. Useful for changing the type of units a group uses.
RemoveUnit(Unit Handle); // Removes the specified unit from the group
HasBeenAttacked(); // Checks if the group has been attacked by enemy units
SetDeleteWhenEmpty(0 = false, 1 = true); // Deletes the group if all units in it have been destroyed (assumed?)
Now, some examples of how you would use some of those functions:
// Example
// Create a group to defend our base
FightGroup BaseDefense; // Note: For now, this should be a global variable
...
(in InitProc)
// Initialize it
BaseDefense = CreateFightGroup(Player[playerAI]);
// Create some units for it
Unit Unit1;
TethysGame::CreateUnit(Unit1, mapLynx, ... );
BaseDefense.TakeUnit(Unit1);
TethysGame::CreateUnit(Unit1, mapLynx, ... );
BaseDefense.TakeUnit(Unit1);
TethysGame::CreateUnit(Unit1, mapLynx, ... );
BaseDefense.TakeUnit(Unit1);
// Do some stuff to the group
BaseDefense.SetLights(1);
BaseDefense.SetTargCount(mapLynx, mapLaser, 3);
...
// If we research Rail Gun, replace the Lasers with Rail Guns
SCRIPT_API void RailGunResearched()
{
BaseDefense.ClearTargCount();
BaseDefense.SetTargCount(mapLynx, mapRailGun, 3);
}
...
// If we get Thor's Hammer, destroy this group
SCRIPT_API void ThorsResearched()
{
BaseDefense.Destroy();
}
Now let's talk about the special functions available to the different types of groups
Bulding GroupsDespite the name, building groups don't necessarily deal with construction. There are four sub-types of the building group:
1) Building Construction
2) Building Repair
3) Mine Construction
4) Vehicle (Re)Building
5) Walls and Tubes
Let's start at the top. You may have already figured this out, but building construction groups are what you use to tell the AI to build structures. Such a group consists of three things:
1) ConVecs
2) A Structure Factory
3) A list of buildings to build (and rebuild if they get destroyed. This should include any buildings the AI starts the game with)
Repair groups are simple. You just need a ConVec (can reuse one from the build group), a Repair Vehicle, or a Spider. I'll explain using them below.
Mine construction is basically the same as construction, except you need:
1) Robo-Miner
2) A list of all mines to be built/rebuilt
Rebuilding vehicles is easy. You need:
1) At least one Vehicle Factory
2) A list of all unit groups, with an assigned priority
Building walls and tubes are just like structures. You need:
1) Earthworker(s)
2) List of tubes to build/rebuild
3) List of Normal Walls to build/rebuild
4) List of Lava Walls to build/rebuild (optional)
5) List of Microbe Walls to build/rebuild (optional)
All Building Group Functions:
// Construction
RecordBuilding(LOCATION(x, y), Unit Type, Cargo Type); // Tells the AI what type of building should be at the specified location. More info below.
RecordTube(LOCATION(x, y) ); // Tells the AI that a tube needs to be at the specified location.
RecordWall(LOCATION(x, y), Wall Type); // Tells the AI that a wall of the specified type must be at the specified location.
// Building Vehicles
RecordVehReinforceGroup(Group, Priority); // Tells the VF(s) to build units for the specified group until it's target count is reached
UnRecordVehGroup(Group); // Tells the VF(s) to stop reinforcing the specified group
// Generic functions
SetRect(Region); // Specifies where the units will wait when they're idle.
Examples:
// Demonstrating how to build a base and setup vehicle rebuilding
BuildingGroup Construction;
BuildingGroup RebuildMines;
BuildingGroup Reinforce;
...
// Create the Construction building group
Construction = CreateBuildingGroup(Player[1]);
// Add the units to the group
MAP_RECT ConVecBox(225+31, 71-1, 232+31, 79-1);
Construction.SetRect(ConVecBox);
Construction.TakeUnit(SFact);
Construction.TakeUnit(ConVec1);
Construction.TakeUnit(ConVec2);
Construction.TakeUnit(ConVec3);
Construction.SetTargCount(mapConVec, mapNone, 3);
// Record buildings to the list
Construction.RecordBuilding(LOCATION(233+31, 74-1), mapCommandCenter, mapNone); // How are we going to rebuild the CC?
Construction.RecordBuilding(LOCATION(229+31, 73-1), mapStructureFactory, mapNone);
...
// New buildings
Construction.RecordBuilding(LOCATION(252+31, 116-1), mapMHDGenerator, mapNone);
// Create the RebuildMines building group
RebuildMines = CreateBuildingGroup(Player[1]);
// Add the units to the group
MAP_RECT MinerBox(240+31, 78-1, 244+31, 81-1);
RebuildMines.SetRect(MinerBox);
RebuildMines.TakeUnit(Miner);
RebuildMines.TakeUnit(COreMine);
RebuildMines.TakeUnit(ROreMine);
RebuildMines.SetTargCount(mapRoboMiner, mapNone, 1);
RebuildMines.SetTargCount(mapCommonOreMine, mapNone, 2);
// Record the mines
RebuildMines.RecordBuilding(LOCATION(241+31, 89-1), mapCommonOreMine, mapNone);
RebuildMines.RecordBuilding(LOCATION(245+31, 112-1), mapCommonOreMine, mapNone);
// Setup the Reinforce building group
Reinforce = CreateBuildingGroup(Player[1]);
// Assign the Vehicle Factories and Arachnid Factory to the group
Reinforce.TakeUnit(VFact1);
Reinforce.TakeUnit(VFact2);
Reinforce.TakeUnit(VFact3);
Reinforce.TakeUnit(AFact);
// Setup the reinforcement info
Reinforce.RecordVehReinforceGroup(CommonMining1, 1500);
Reinforce.RecordVehReinforceGroup(CommonMining2, 1500);
Reinforce.RecordVehReinforceGroup(Construction, 1000);
Reinforce.RecordVehReinforceGroup(EWorker, 500);
Reinforce.RecordVehReinforceGroup(RebuildMines, 3000);
You should give that code a try. Go make a quick little colony game demo where the AI just builds a little base and some vehicles. Might want to give it unlimited resources for now. Also, keep in mind that the order you record a building to the build list is the order it will be rebuilt in.
Okay, go write that little AI demo! I'll be waiting when you get back, and we'll move on to mining and combat.