The AI now only uses units which have their AI set to active (as intended)

This commit is contained in:
Andrettin 2015-11-24 22:50:15 +01:00
parent 415d839b58
commit dc4391b8c3
17 changed files with 109 additions and 34 deletions

View file

@ -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>

View file

@ -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) {

View file

@ -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;

View file

@ -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;

View file

@ -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();

View file

@ -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));

View file

@ -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

View file

@ -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.

View file

@ -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")) {

View file

@ -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

View file

@ -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

View file

@ -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);

View file

@ -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;

View file

@ -26,6 +26,7 @@ class CPlayer
const int Revenue[MaxCosts];
const int UnitTypesCount[UnitTypeMax];
const int UnitTypesAiActiveCount[UnitTypeMax];
bool AiEnabled;
int NumBuildings;

View file

@ -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) {

View file

@ -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) {

View file

@ -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;
}