The AI now only uses units which have their AI set to active (as intended)
This commit is contained in:
parent
415d839b58
commit
dc4391b8c3
17 changed files with 109 additions and 34 deletions
|
@ -651,8 +651,8 @@ Possible values for <i>property</i>:
|
|||
<dt>RaceName</dt>
|
||||
<dd>Name of race.
|
||||
</dd>
|
||||
<dt>Ressources</dt>
|
||||
<dd>The amount of ressources available for the ressource whose name is given as third argument.
|
||||
<dt>Resources</dt>
|
||||
<dd>The amount of resources available for the resource whose name is given as third argument.
|
||||
</dd>
|
||||
<dt>UnitTypesCount</dt>
|
||||
<dd>The amount of units whose type is given as third argument.
|
||||
|
@ -691,7 +691,7 @@ Possible values for <i>property</i>:
|
|||
<dd>Total number of buildings.
|
||||
</dd>
|
||||
<dt>TotalResources</dt>
|
||||
<dd>Total ressources of the <i>resource</i> type collected by the player.
|
||||
<dd>Total resources of the <i>resource</i> type collected by the player.
|
||||
</dd>
|
||||
<dt>TotalRazings</dt>
|
||||
<dd>Total buildings destroyed.
|
||||
|
@ -728,10 +728,23 @@ Get a unit's variable.
|
|||
<dt>unit</dt>
|
||||
<dd>Unit to get info for.</dd>
|
||||
<dt>VariableName</dt>
|
||||
<dd>Name of the variable to get info for. Also takes "IndividualUpgrade" instead of a variable name, to get whether the unit has acquired a particular individual upgrade. Alternatively, takes "Idle" to check whether the unit is idle or not.</dd>
|
||||
<dd>Name of the variable to get info for.</dd>
|
||||
<dt>third_element</dt>
|
||||
<dd>Used if getting whether the unit has an individual upgrade, taking the upgrade's ident.</dd>
|
||||
<dd>Used for certain alternate uses of the function, described below.</dd>
|
||||
</dl>
|
||||
<p>
|
||||
|
||||
Besides variable names, the <i>VariableName</i> field takes the following alternate values:
|
||||
<dl>
|
||||
<dt>IndividualUpgrade</dt>
|
||||
<dd>Use this to get whether the unit has a certain individual upgrade. Use the upgrade's ident in the <i>third_element</i> field.
|
||||
</dd>
|
||||
<dt>Active</dt>
|
||||
<dd>Use this to get whether the unit's AI is active.
|
||||
</dd>
|
||||
<dt>Idle</dt>
|
||||
<dd>Use this to get whether the unit is idle.
|
||||
</dd>
|
||||
|
||||
<h4>Example</h4>
|
||||
|
||||
|
@ -1324,7 +1337,7 @@ Possible values for <i>property</i>:
|
|||
<dt>RaceName</dt>
|
||||
<dd>Name of the race of the player. Don't change this value during the game.
|
||||
</dd>
|
||||
<dt>Ressources</dt>
|
||||
<dt>Resources</dt>
|
||||
<dd>The amount of resources available of the <i>resource</i> kind.
|
||||
</dd>
|
||||
<dt>UnitLimit</dt>
|
||||
|
@ -1346,7 +1359,7 @@ Possible values for <i>property</i>:
|
|||
<dd>Total number of buildings.
|
||||
</dd>
|
||||
<dt>TotalResources</dt>
|
||||
<dd>Total ressources of the <i>resource</i> type collected by the player.
|
||||
<dd>Total resources of the <i>resource</i> type collected by the player.
|
||||
</dd>
|
||||
<dt>TotalRazings</dt>
|
||||
<dd>Total buildings destroyed.
|
||||
|
@ -1409,12 +1422,22 @@ Set the amount of VariableName of the unit.
|
|||
<dt>unit</dt>
|
||||
<dd>Unit to set the info for.</dd>
|
||||
<dt>VariableName</dt>
|
||||
<dd>Variable to set. Also takes "IndividualUpgrade" instead of a variable name, to make the unit acquire or lose an individual upgrade.</dd>
|
||||
<dd>Variable to set.</dd>
|
||||
<dt>amount</dt>
|
||||
<dd>New amount of VariableName for the unit. Alternatively, if setting an individual upgrade for the unit, this field takes the ident of the upgrade.</dd>
|
||||
<dd>New amount of VariableName for the unit.</dd>
|
||||
<dt>fourth_element</dt>
|
||||
<dd>Used if setting an individual upgrade for the unit. Use a boolean value for whether the unit will acquire or lose the individual upgrade.</dd>
|
||||
<dd>Used for certain alternative uses of the function, described below.</dd>
|
||||
</dl>
|
||||
<p>
|
||||
|
||||
Besides variable names, the <i>VariableName</i> field takes the following alternate string values:
|
||||
<dl>
|
||||
<dt>IndividualUpgrade</dt>
|
||||
<dd>Use this to make the unit acquire or lose an individual upgrade. Use the upgrade's ident in the <i>amount</i> field, and whether the upgrade should be acquired or lost in the <i>fourth_element</i> field (set it to true or false).
|
||||
</dd>
|
||||
<dt>Active</dt>
|
||||
<dd>Use this to set the unit's AI to active. Use true or false for the <i>amount</i> field.
|
||||
</dd>
|
||||
|
||||
<h4>Example</h4>
|
||||
|
||||
|
|
|
@ -356,6 +356,9 @@ bool COrder_Build::StartBuilding(CUnit &unit, CUnit &ontop)
|
|||
|
||||
// HACK: the building is not ready yet
|
||||
build->Player->UnitTypesCount[type.Slot]--;
|
||||
if (build->Active) {
|
||||
build->Player->UnitTypesAiActiveCount[type.Slot]--;
|
||||
}
|
||||
|
||||
// We need somebody to work on it.
|
||||
if (!type.BuilderOutside) {
|
||||
|
|
|
@ -155,6 +155,9 @@ static void Finish(COrder_Built &order, CUnit &unit)
|
|||
|
||||
// HACK: the building is ready now
|
||||
player.UnitTypesCount[type.Slot]++;
|
||||
if (unit.Active) {
|
||||
player.UnitTypesAiActiveCount[type.Slot]++;
|
||||
}
|
||||
unit.Constructed = 0;
|
||||
if (unit.Frame < 0) {
|
||||
unit.Frame = -1;
|
||||
|
|
|
@ -106,6 +106,10 @@ static int TransformUnitIntoType(CUnit &unit, const CUnitType &newtype)
|
|||
CPlayer &player = *unit.Player;
|
||||
player.UnitTypesCount[oldtype.Slot]--;
|
||||
player.UnitTypesCount[newtype.Slot]++;
|
||||
if (unit.Active) {
|
||||
player.UnitTypesAiActiveCount[oldtype.Slot]--;
|
||||
player.UnitTypesAiActiveCount[newtype.Slot]++;
|
||||
}
|
||||
|
||||
player.Demand += newtype.Demand - oldtype.Demand;
|
||||
player.Supply += newtype.Supply - oldtype.Supply;
|
||||
|
|
|
@ -194,16 +194,7 @@ static void AiCheckUnits()
|
|||
int counter[UnitTypeMax];
|
||||
AiGetBuildRequestsCount(*AiPlayer, counter);
|
||||
|
||||
// Remove non active units.
|
||||
const int unitCount = AiPlayer->Player->GetUnitCount();
|
||||
for (int i = 0; i < unitCount; ++i) {
|
||||
const CUnit &unit = AiPlayer->Player->GetUnit(i);
|
||||
|
||||
if (!unit.Active) {
|
||||
counter[unit.Type->Slot]--;
|
||||
}
|
||||
}
|
||||
const int *unit_types_count = AiPlayer->Player->UnitTypesCount;
|
||||
const int *unit_types_count = AiPlayer->Player->UnitTypesAiActiveCount;
|
||||
|
||||
// Look if some unit-types are missing.
|
||||
int n = AiPlayer->UnitTypeRequests.size();
|
||||
|
|
|
@ -575,7 +575,7 @@ bool AiForceManager::Assign(CUnit &unit, int force)
|
|||
void AiForceManager::CheckUnits(int *counter)
|
||||
{
|
||||
int attacking[UnitTypeMax];
|
||||
const int *unit_types_count = AiPlayer->Player->UnitTypesCount;
|
||||
const int *unit_types_count = AiPlayer->Player->UnitTypesAiActiveCount;
|
||||
|
||||
memset(attacking, 0, sizeof(attacking));
|
||||
|
||||
|
|
|
@ -270,7 +270,7 @@ static int AiBuildBuilding(const CUnitType &type, CUnitType &building, const Vec
|
|||
{
|
||||
std::vector<CUnit *> table;
|
||||
|
||||
FindPlayerUnitsByType(*AiPlayer->Player, type, table);
|
||||
FindPlayerUnitsByType(*AiPlayer->Player, type, table, true);
|
||||
|
||||
int num = 0;
|
||||
|
||||
|
@ -316,7 +316,7 @@ static bool AiRequestedTypeAllowed(const CPlayer &player, const CUnitType &type)
|
|||
for (size_t i = 0; i != size; ++i) {
|
||||
CUnitType &builder = *AiHelpers.Build[type.Slot][i];
|
||||
|
||||
if (player.UnitTypesCount[builder.Slot] > 0
|
||||
if (player.UnitTypesAiActiveCount[builder.Slot] > 0
|
||||
&& CheckDependByType(player, type)) {
|
||||
return true;
|
||||
}
|
||||
|
@ -627,7 +627,7 @@ static bool AiTrainUnit(const CUnitType &type, CUnitType &what)
|
|||
{
|
||||
std::vector<CUnit *> table;
|
||||
|
||||
FindPlayerUnitsByType(*AiPlayer->Player, type, table);
|
||||
FindPlayerUnitsByType(*AiPlayer->Player, type, table, true);
|
||||
for (size_t i = 0; i != table.size(); ++i) {
|
||||
CUnit &unit = *table[i];
|
||||
|
||||
|
@ -681,7 +681,7 @@ static int AiMakeUnit(CUnitType &typeToMake, const Vec2i &nearPos)
|
|||
continue;
|
||||
}
|
||||
|
||||
const int *unit_count = AiPlayer->Player->UnitTypesCount;
|
||||
const int *unit_count = AiPlayer->Player->UnitTypesAiActiveCount;
|
||||
for (unsigned int i = 0; i < table.size(); ++i) {
|
||||
//
|
||||
// The type for builder/trainer is available
|
||||
|
@ -716,7 +716,7 @@ static bool AiResearchUpgrade(const CUnitType &type, CUpgrade &what)
|
|||
{
|
||||
std::vector<CUnit *> table;
|
||||
|
||||
FindPlayerUnitsByType(*AiPlayer->Player, type, table);
|
||||
FindPlayerUnitsByType(*AiPlayer->Player, type, table, true);
|
||||
for (size_t i = 0; i != table.size(); ++i) {
|
||||
CUnit &unit = *table[i];
|
||||
|
||||
|
@ -760,7 +760,7 @@ void AiAddResearchRequest(CUpgrade *upgrade)
|
|||
return;
|
||||
}
|
||||
|
||||
const int *unit_count = AiPlayer->Player->UnitTypesCount;
|
||||
const int *unit_count = AiPlayer->Player->UnitTypesAiActiveCount;
|
||||
for (unsigned int i = 0; i < table.size(); ++i) {
|
||||
// The type is available
|
||||
if (unit_count[table[i]->Slot]
|
||||
|
@ -785,7 +785,7 @@ static bool AiUpgradeTo(const CUnitType &type, CUnitType &what)
|
|||
std::vector<CUnit *> table;
|
||||
|
||||
// Remove all units already doing something.
|
||||
FindPlayerUnitsByType(*AiPlayer->Player, type, table);
|
||||
FindPlayerUnitsByType(*AiPlayer->Player, type, table, true);
|
||||
for (size_t i = 0; i != table.size(); ++i) {
|
||||
CUnit &unit = *table[i];
|
||||
|
||||
|
@ -831,7 +831,7 @@ void AiAddUpgradeToRequest(CUnitType &type)
|
|||
return;
|
||||
}
|
||||
|
||||
const int *unit_count = AiPlayer->Player->UnitTypesCount;
|
||||
const int *unit_count = AiPlayer->Player->UnitTypesAiActiveCount;
|
||||
for (unsigned int i = 0; i < table.size(); ++i) {
|
||||
//
|
||||
// The type is available
|
||||
|
@ -1247,7 +1247,7 @@ static bool AiRepairBuilding(const CPlayer &player, const CUnitType &type, CUnit
|
|||
// AI shouldn't send workers that are far away from repair point
|
||||
// Selection of mining workers.
|
||||
std::vector<CUnit *> table;
|
||||
FindPlayerUnitsByType(*AiPlayer->Player, type, table);
|
||||
FindPlayerUnitsByType(*AiPlayer->Player, type, table, true);
|
||||
int num = 0;
|
||||
for (size_t i = 0; i != table.size(); ++i) {
|
||||
CUnit &unit = *table[i];
|
||||
|
@ -1305,7 +1305,7 @@ static int AiRepairUnit(CUnit &unit)
|
|||
return 0;
|
||||
}
|
||||
|
||||
const int *unit_count = AiPlayer->Player->UnitTypesCount;
|
||||
const int *unit_count = AiPlayer->Player->UnitTypesAiActiveCount;
|
||||
for (unsigned int i = 0; i < table.size(); ++i) {
|
||||
//
|
||||
// The type is available
|
||||
|
|
|
@ -631,7 +631,7 @@ static int CclAiWait(lua_State *l)
|
|||
{
|
||||
LuaCheckArgs(l, 1);
|
||||
const CUnitType *type = CclGetUnitType(l);
|
||||
const int *unit_types_count = AiPlayer->Player->UnitTypesCount;
|
||||
const int *unit_types_count = AiPlayer->Player->UnitTypesAiActiveCount;
|
||||
const AiRequestType *autt = FindInUnitTypeRequests(type);
|
||||
if (!autt) {
|
||||
// Look if we have this unit-type.
|
||||
|
|
|
@ -88,6 +88,11 @@ int GetPlayerData(const int player, const char *prop, const char *arg)
|
|||
CUnitType *type = UnitTypeByIdent(unit);
|
||||
Assert(type);
|
||||
return Players[player].UnitTypesCount[type->Slot];
|
||||
} else if (!strcmp(prop, "UnitTypesAiActiveCount")) {
|
||||
const std::string unit(arg);
|
||||
CUnitType *type = UnitTypeByIdent(unit);
|
||||
Assert(type);
|
||||
return Players[player].UnitTypesAiActiveCount[type->Slot];
|
||||
} else if (!strcmp(prop, "AiEnabled")) {
|
||||
return Players[player].AiEnabled;
|
||||
} else if (!strcmp(prop, "TotalNumUnits")) {
|
||||
|
|
|
@ -109,6 +109,7 @@ public:
|
|||
|
||||
// FIXME: shouldn't use the constant
|
||||
int UnitTypesCount[UnitTypeMax]; /// total units of unit-type
|
||||
int UnitTypesAiActiveCount[UnitTypeMax]; /// total units of unit-type that have their AI set to active
|
||||
|
||||
bool AiEnabled; /// handle AI on local computer
|
||||
PlayerAi *Ai; /// Ai structure pointer
|
||||
|
|
|
@ -314,7 +314,7 @@ extern bool FindTerrainType(int movemask, int resmask, int range,
|
|||
extern void FindUnitsByType(const CUnitType &type, std::vector<CUnit *> &units, bool everybody = false);
|
||||
|
||||
/// Find all units of this type of the player
|
||||
extern void FindPlayerUnitsByType(const CPlayer &player, const CUnitType &type, std::vector<CUnit *> &units);
|
||||
extern void FindPlayerUnitsByType(const CPlayer &player, const CUnitType &type, std::vector<CUnit *> &units, bool ai_active = false);
|
||||
/// Return any unit on that map tile
|
||||
extern CUnit *UnitOnMapTile(const Vec2i &pos, unsigned int type);// = -1);
|
||||
/// Return possible attack target on that map area
|
||||
|
|
|
@ -702,6 +702,7 @@ void CPlayer::Init(/* PlayerTypes */ int type)
|
|||
}
|
||||
|
||||
memset(this->UnitTypesCount, 0, sizeof(this->UnitTypesCount));
|
||||
memset(this->UnitTypesAiActiveCount, 0, sizeof(this->UnitTypesAiActiveCount));
|
||||
|
||||
this->Supply = 0;
|
||||
this->Demand = 0;
|
||||
|
@ -754,6 +755,7 @@ void CPlayer::Clear()
|
|||
memset(Incomes, 0, sizeof(Incomes));
|
||||
memset(Revenue, 0, sizeof(Revenue));
|
||||
memset(UnitTypesCount, 0, sizeof(UnitTypesCount));
|
||||
memset(UnitTypesAiActiveCount, 0, sizeof(UnitTypesAiActiveCount));
|
||||
AiEnabled = false;
|
||||
Ai = 0;
|
||||
this->Units.resize(0);
|
||||
|
|
|
@ -671,6 +671,12 @@ static int CclGetPlayerData(lua_State *l)
|
|||
Assert(type);
|
||||
lua_pushnumber(l, p->UnitTypesCount[type->Slot]);
|
||||
return 1;
|
||||
} else if (!strcmp(data, "UnitTypesAiActiveCount")) {
|
||||
LuaCheckArgs(l, 3);
|
||||
CUnitType *type = CclGetUnitType(l);
|
||||
Assert(type);
|
||||
lua_pushnumber(l, p->UnitTypesAiActiveCount[type->Slot]);
|
||||
return 1;
|
||||
} else if (!strcmp(data, "AiEnabled")) {
|
||||
lua_pushboolean(l, p->AiEnabled);
|
||||
return 1;
|
||||
|
|
|
@ -26,6 +26,7 @@ class CPlayer
|
|||
const int Revenue[MaxCosts];
|
||||
|
||||
const int UnitTypesCount[UnitTypeMax];
|
||||
const int UnitTypesAiActiveCount[UnitTypeMax];
|
||||
bool AiEnabled;
|
||||
|
||||
int NumBuildings;
|
||||
|
|
|
@ -526,6 +526,9 @@ static int CclUnit(lua_State *l)
|
|||
DebugPrint("HACK: the building is not ready yet\n");
|
||||
// HACK: the building is not ready yet
|
||||
unit->Player->UnitTypesCount[type->Slot]--;
|
||||
if (unit->Active) {
|
||||
unit->Player->UnitTypesAiActiveCount[type->Slot]--;
|
||||
}
|
||||
}
|
||||
} else if (!strcmp(value, "critical-order")) {
|
||||
lua_rawgeti(l, 2, j + 1);
|
||||
|
@ -1108,6 +1111,9 @@ static int CclGetUnitVariable(lua_State *l)
|
|||
LuaError(l, "Individual upgrade \"%s\" doesn't exist." _C_ upgrade_ident.c_str());
|
||||
}
|
||||
return 1;
|
||||
} else if (!strcmp(value, "Active")) {
|
||||
lua_pushboolean(l, unit->Active);
|
||||
return 1;
|
||||
} else if (!strcmp(value, "Idle")) {
|
||||
lua_pushboolean(l, unit->IsIdle());
|
||||
return 1;
|
||||
|
@ -1171,6 +1177,19 @@ static int CclSetUnitVariable(lua_State *l)
|
|||
} else {
|
||||
LuaError(l, "Individual upgrade \"%s\" doesn't exist." _C_ upgrade_ident.c_str());
|
||||
}
|
||||
} else if (!strcmp(name, "Active")) {
|
||||
bool ai_active = LuaToBoolean(l, 3);
|
||||
if (ai_active != unit->Active) {
|
||||
if (ai_active) {
|
||||
unit->Player->UnitTypesAiActiveCount[unit->Type->Slot]++;
|
||||
} else {
|
||||
unit->Player->UnitTypesAiActiveCount[unit->Type->Slot]--;
|
||||
if (unit->Player->UnitTypesAiActiveCount[unit->Type->Slot] < 0) { // if unit AI active count is negative, something wrong happened
|
||||
fprintf(stderr, "Player %d has a negative %s AI active count of %d.\n", unit->Player->Index, unit->Type->Ident.c_str(), unit->Player->UnitTypesAiActiveCount[unit->Type->Slot]);
|
||||
}
|
||||
}
|
||||
}
|
||||
unit->Active = ai_active;
|
||||
} else {
|
||||
const int index = UnitTypeVar.VariableNameLookup[name];// User variables
|
||||
if (index == -1) {
|
||||
|
|
|
@ -712,6 +712,9 @@ void CUnit::AssignToPlayer(CPlayer &player)
|
|||
}
|
||||
}
|
||||
player.UnitTypesCount[type.Slot]++;
|
||||
if (Active) {
|
||||
player.UnitTypesAiActiveCount[type.Slot]++;
|
||||
}
|
||||
player.Demand += type.Demand; // food needed
|
||||
}
|
||||
|
||||
|
@ -1279,6 +1282,9 @@ void UnitLost(CUnit &unit)
|
|||
}
|
||||
if (unit.CurrentAction() != UnitActionBuilt) {
|
||||
player.UnitTypesCount[type.Slot]--;
|
||||
if (unit.Active) {
|
||||
player.UnitTypesAiActiveCount[type.Slot]--;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -1779,6 +1785,9 @@ void CUnit::ChangeOwner(CPlayer &newplayer)
|
|||
newplayer.NumBuildings++;
|
||||
}
|
||||
newplayer.UnitTypesCount[Type->Slot]++;
|
||||
if (Active) {
|
||||
newplayer.UnitTypesAiActiveCount[Type->Slot]++;
|
||||
}
|
||||
|
||||
//apply the upgrades of the new player, if the old one doesn't have that upgrade
|
||||
for (int z = 0; z < NumUpgradeModifiers; ++z) {
|
||||
|
|
|
@ -540,11 +540,19 @@ void FindUnitsByType(const CUnitType &type, std::vector<CUnit *> &units, bool ev
|
|||
** @param type type of unit requested
|
||||
** @param table table in which we have to store the units
|
||||
*/
|
||||
void FindPlayerUnitsByType(const CPlayer &player, const CUnitType &type, std::vector<CUnit *> &table)
|
||||
void FindPlayerUnitsByType(const CPlayer &player, const CUnitType &type, std::vector<CUnit *> &table, bool ai_active)
|
||||
{
|
||||
const int nunits = player.GetUnitCount();
|
||||
int typecount = player.UnitTypesCount[type.Slot];
|
||||
|
||||
if (ai_active) {
|
||||
typecount = player.UnitTypesAiActiveCount[type.Slot];
|
||||
}
|
||||
|
||||
if (typecount < 0) { // if unit type count is negative, something wrong happened
|
||||
fprintf(stderr, "Player %d has a negative %s unit type count of %d.\n", player.Index, type.Ident.c_str(), typecount);
|
||||
}
|
||||
|
||||
if (typecount == 0) {
|
||||
return;
|
||||
}
|
||||
|
|
Loading…
Reference in a new issue