Some Clean up in Ai Module
Fix missing RefDecrease in AiForce Remove unused flag MustTransport remove Big unused Array units_with_resource[MaxCost][UnitMax] in AiCollectResources
This commit is contained in:
parent
e42b3eb6a4
commit
de0530e856
7 changed files with 243 additions and 344 deletions
|
@ -316,8 +316,8 @@ static void SaveAiPlayer(CFile *file, int plynr, PlayerAi *ai)
|
|||
file->printf(" %d, \"%s\",", UnitNumber(aiunit),
|
||||
aiunit.Type->Ident.c_str());
|
||||
}
|
||||
file->printf("},\n \"state\", %d, \"goalx\", %d, \"goaly\", %d, \"must-transport\", %d,",
|
||||
ai->Force[i].State, ai->Force[i].GoalPos.x, ai->Force[i].GoalPos.y, ai->Force[i].MustTransport);
|
||||
file->printf("},\n \"state\", %d, \"goalx\", %d, \"goaly\", %d,",
|
||||
ai->Force[i].State, ai->Force[i].GoalPos.x, ai->Force[i].GoalPos.y);
|
||||
file->printf("},\n");
|
||||
}
|
||||
|
||||
|
|
|
@ -44,8 +44,6 @@
|
|||
#include "actions.h"
|
||||
#include "map.h"
|
||||
#include "depend.h"
|
||||
#include "pathfinder.h"
|
||||
#include "player.h"
|
||||
|
||||
/*----------------------------------------------------------------------------
|
||||
-- Types
|
||||
|
@ -78,10 +76,27 @@ struct AiForceEnemyFinder {
|
|||
AiForceEnemyFinder(AiForce *force): enemy(NULL) {
|
||||
force->Units.for_each_if(*this);
|
||||
}
|
||||
|
||||
};
|
||||
|
||||
struct AiForceAttackSender {
|
||||
class AiForceAttackSender {
|
||||
public:
|
||||
// Send all units in the force to enemy at pos.
|
||||
AiForceAttackSender(int force, const Vec2i &pos) : goalPos(pos), delta(0) {
|
||||
DebugPrint("%d: Attacking with force #%d\n" _C_ AiPlayer->Player->Index _C_ force);
|
||||
AiForce *fptr = &AiPlayer->Force[force];
|
||||
fptr->Attacking = true;
|
||||
fptr->State = AiForceAttackingState_Attacking;
|
||||
fptr->Units.for_each(*this);
|
||||
}
|
||||
|
||||
AiForceAttackSender(AiForce *force, const Vec2i &pos) :
|
||||
goalPos(pos), delta(0) {
|
||||
DebugPrint("%d: Attacking with force #%lu\n" _C_ AiPlayer->Player->Index
|
||||
_C_ (long unsigned int)(force - &(AiPlayer->Force[0])));
|
||||
force->Attacking = true;
|
||||
force->State = AiForceAttackingState_Attacking;
|
||||
force->Units.for_each(*this);
|
||||
}
|
||||
|
||||
inline void operator() (CUnit *const unit) {
|
||||
// this may be problem if units are in bunker and we want sent
|
||||
|
@ -94,32 +109,13 @@ struct AiForceAttackSender {
|
|||
CommandUnload(*unit, goalPos, NULL, FlushCommands);
|
||||
} else if (unit->Type->CanAttack) {
|
||||
CommandAttack(*unit, goalPos, NULL, FlushCommands);
|
||||
} else /*if (force->State == 2) */{
|
||||
} else {
|
||||
CommandMove(*unit, goalPos, FlushCommands);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
//
|
||||
// Send all units in the force to enemy at x,y.
|
||||
//
|
||||
AiForceAttackSender(int force, const Vec2i &pos) : goalPos(pos), delta(0) {
|
||||
DebugPrint("%d: Attacking with force #%d\n" _C_ AiPlayer->Player->Index _C_ force);
|
||||
AiForce *fptr = &AiPlayer->Force[force];
|
||||
fptr->Attacking = true;
|
||||
fptr->State = AI_FORCE_STATE_ATTACKING;
|
||||
fptr->Units.for_each(*this);
|
||||
}
|
||||
|
||||
AiForceAttackSender(AiForce *force, const Vec2i &pos) :
|
||||
goalPos(pos), delta(0) {
|
||||
DebugPrint("%d: Attacking with force #%lu\n" _C_ AiPlayer->Player->Index
|
||||
_C_ (long unsigned int)(force - &(AiPlayer->Force[0])));
|
||||
force->Attacking = true;
|
||||
force->State = AI_FORCE_STATE_ATTACKING;
|
||||
force->Units.for_each(*this);
|
||||
}
|
||||
|
||||
private:
|
||||
Vec2i goalPos;
|
||||
int delta;
|
||||
};
|
||||
|
@ -154,22 +150,16 @@ void AiResetUnitTypeEquiv()
|
|||
*/
|
||||
void AiNewUnitTypeEquiv(CUnitType *a, CUnitType *b)
|
||||
{
|
||||
int find;
|
||||
int replace;
|
||||
int i;
|
||||
|
||||
find = UnitTypeEquivs[a->Slot];
|
||||
replace = UnitTypeEquivs[b->Slot];
|
||||
int find = UnitTypeEquivs[a->Slot];
|
||||
int replace = UnitTypeEquivs[b->Slot];
|
||||
|
||||
// Always record equivalences with the lowest unittype.
|
||||
if (find < replace) {
|
||||
i = find;
|
||||
find = replace;
|
||||
replace = i;
|
||||
std::swap(find, replace);
|
||||
}
|
||||
|
||||
// Then just find & replace in UnitTypeEquivs...
|
||||
for (i = 0; i <= UnitTypeMax; ++i) {
|
||||
for (unsigned int i = 0; i <= UnitTypeMax; ++i) {
|
||||
if (UnitTypeEquivs[i] == find) {
|
||||
UnitTypeEquivs[i] = replace;
|
||||
}
|
||||
|
@ -194,12 +184,21 @@ int AiFindUnitTypeEquiv(const CUnitType &unittype, int *result)
|
|||
if (UnitTypeEquivs[i] == search) {
|
||||
// Found one
|
||||
result[count] = i;
|
||||
count++;
|
||||
++count;
|
||||
}
|
||||
}
|
||||
return count;
|
||||
}
|
||||
|
||||
class UnitTypePrioritySorter_Decreasing
|
||||
{
|
||||
public:
|
||||
bool operator () (int lhs, int rhs) const
|
||||
{
|
||||
return UnitTypes[lhs]->Priority > UnitTypes[rhs]->Priority;
|
||||
}
|
||||
};
|
||||
|
||||
/**
|
||||
** Find All unittypes equivalent to a given one, and which are available
|
||||
** UnitType are returned in the prefered order ( ie palladin >> knight... )
|
||||
|
@ -226,35 +225,26 @@ int AiFindAvailableUnitTypeEquiv(const CUnitType &unittype, int *usableTypes)
|
|||
}
|
||||
|
||||
// 3 - Sort by level
|
||||
// We won't have usableTypesCount>4, so simple sort should do it
|
||||
for (int i = 0; i < usableTypesCount - 1; ++i) {
|
||||
int bestlevel = UnitTypes[usableTypes[i]]->Priority;
|
||||
for (int j = i + 1; j < usableTypesCount; ++j) {
|
||||
const int curlevel = UnitTypes[usableTypes[j]]->Priority;
|
||||
std::sort(usableTypes, usableTypes + usableTypesCount, UnitTypePrioritySorter_Decreasing());
|
||||
|
||||
if (curlevel > bestlevel) {
|
||||
std::swap(usableTypes[j], usableTypes[i]);
|
||||
bestlevel = curlevel;
|
||||
}
|
||||
}
|
||||
}
|
||||
return usableTypesCount;
|
||||
}
|
||||
|
||||
/* =========================== FORCES ========================== */
|
||||
|
||||
struct AiForceCounter {
|
||||
unsigned int *data;//[UnitTypeMax + 1];
|
||||
|
||||
inline void operator() (CUnit *const unit) {
|
||||
data[UnitTypeEquivs[unit->Type->Slot]]++;
|
||||
}
|
||||
|
||||
AiForceCounter(CUnitCache &units, unsigned int *d, const size_t len): data(d)
|
||||
class AiForceCounter
|
||||
{
|
||||
public:
|
||||
AiForceCounter(CUnitCache &units, unsigned int *d, const size_t len) : data(d)
|
||||
{
|
||||
memset(data, 0, len);
|
||||
units.for_each(*this);
|
||||
}
|
||||
inline void operator() (CUnit *const unit) {
|
||||
data[UnitTypeEquivs[unit->Type->Slot]]++;
|
||||
}
|
||||
private:
|
||||
unsigned int *data;//[UnitTypeMax + 1];
|
||||
};
|
||||
|
||||
void AiForce::CountTypes(unsigned int *counter, const size_t len) {
|
||||
|
@ -270,9 +260,7 @@ void AiForce::CountTypes(unsigned int *counter, const size_t len) {
|
|||
*/
|
||||
bool AiForce::IsBelongsTo(const CUnitType *type)
|
||||
{
|
||||
AiUnitType *aitype;
|
||||
bool flag = false;
|
||||
int slot;
|
||||
unsigned int counter[UnitTypeMax + 1];
|
||||
|
||||
//
|
||||
|
@ -285,11 +273,12 @@ bool AiForce::IsBelongsTo(const CUnitType *type)
|
|||
//
|
||||
Completed = true;
|
||||
for (unsigned int i = 0; i < UnitTypes.size(); ++i) {
|
||||
aitype = &UnitTypes[i];
|
||||
slot = aitype->Type->Slot;
|
||||
if (aitype->Want > counter[slot]) {
|
||||
const AiUnitType &aitype = UnitTypes[i];
|
||||
const int slot = aitype.Type->Slot;
|
||||
|
||||
if (counter[slot] < aitype.Want) {
|
||||
if (UnitTypeEquivs[type->Slot] == slot) {
|
||||
if (aitype->Want - 1 > counter[slot]) {
|
||||
if (counter[slot] < aitype.Want - 1) {
|
||||
Completed = false;
|
||||
}
|
||||
flag = true;
|
||||
|
@ -303,20 +292,17 @@ bool AiForce::IsBelongsTo(const CUnitType *type)
|
|||
|
||||
/**
|
||||
** Ai clean units in a force.
|
||||
**
|
||||
*/
|
||||
void AiForce::Clean() {
|
||||
|
||||
CUnit *aiunit;
|
||||
void AiForce::Clean()
|
||||
{
|
||||
unsigned int i = 0;
|
||||
//
|
||||
|
||||
// Release all killed units.
|
||||
//
|
||||
while (i != Units.size()) {
|
||||
aiunit = Units[i];
|
||||
CUnit *aiunit = Units[i];
|
||||
|
||||
if (!aiunit->IsAlive()) {
|
||||
aiunit->GroupId = 0;
|
||||
aiunit->RefsDecrease();
|
||||
InternalRemoveUnit(aiunit);
|
||||
Units.Remove(i);
|
||||
continue;
|
||||
}
|
||||
|
@ -331,34 +317,34 @@ void AiForce::Attack(const Vec2i &pos)
|
|||
Clean();
|
||||
|
||||
Attacking = false;
|
||||
if (Units.size() > 0) {
|
||||
Attacking = true;
|
||||
if (Units.size() == 0) {
|
||||
return;
|
||||
}
|
||||
Attacking = true;
|
||||
|
||||
if (goalPos.x == -1 || goalPos.y == -1) {
|
||||
/* Search in entire map */
|
||||
const CUnit *enemy = AiForceEnemyFinder<false>(this).enemy;
|
||||
if (enemy) {
|
||||
goalPos = enemy->tilePos;
|
||||
}
|
||||
if (goalPos.x == -1 || goalPos.y == -1) {
|
||||
/* Search in entire map */
|
||||
const CUnit *enemy = AiForceEnemyFinder<false>(this).enemy;
|
||||
if (enemy) {
|
||||
goalPos = enemy->tilePos;
|
||||
}
|
||||
|
||||
this->GoalPos = goalPos;
|
||||
|
||||
if (goalPos.x == -1 || goalPos.y == -1) {
|
||||
DebugPrint("%d: Need to plan an attack with transporter\n" _C_ AiPlayer->Player->Index);
|
||||
if (State == AI_FORCE_STATE_WAITING && !PlanAttack()) {
|
||||
DebugPrint("%d: Can't transport\n" _C_ AiPlayer->Player->Index);
|
||||
Attacking = false;
|
||||
}
|
||||
return;
|
||||
}
|
||||
|
||||
//
|
||||
// Send all units in the force to enemy.
|
||||
//
|
||||
AiForceAttackSender(this, goalPos);
|
||||
}
|
||||
|
||||
this->GoalPos = goalPos;
|
||||
|
||||
if (goalPos.x == -1 || goalPos.y == -1) {
|
||||
DebugPrint("%d: Need to plan an attack with transporter\n" _C_ AiPlayer->Player->Index);
|
||||
if (State == AiForceAttackingState_Waiting && !PlanAttack()) {
|
||||
DebugPrint("%d: Can't transport\n" _C_ AiPlayer->Player->Index);
|
||||
Attacking = false;
|
||||
}
|
||||
return;
|
||||
}
|
||||
|
||||
//
|
||||
// Send all units in the force to enemy.
|
||||
//
|
||||
AiForceAttackSender(this, goalPos);
|
||||
}
|
||||
|
||||
AiForceManager::AiForceManager() {
|
||||
|
@ -370,13 +356,13 @@ unsigned int AiForceManager::FindFreeForce(int role)
|
|||
{
|
||||
/* find free force */
|
||||
unsigned int f = 0;
|
||||
while (f < forces.size() && (forces[f].State > AI_FORCE_STATE_FREE)) {
|
||||
while (f < forces.size() && (forces[f].State > AiForceAttackingState_Free)) {
|
||||
++f;
|
||||
};
|
||||
if (f == forces.size()) {
|
||||
forces.resize(f + 1);
|
||||
}
|
||||
forces[f].State = AI_FORCE_STATE_WAITING;
|
||||
forces[f].State = AiForceAttackingState_Waiting;
|
||||
forces[f].Role = role;
|
||||
return f;
|
||||
}
|
||||
|
@ -399,18 +385,20 @@ void AiForceManager::Clean()
|
|||
*/
|
||||
bool AiForceManager::Assign(CUnit &unit)
|
||||
{
|
||||
//
|
||||
if (unit.GroupId != 0) {
|
||||
return false;
|
||||
}
|
||||
|
||||
// Check to which force it belongs
|
||||
//
|
||||
for(unsigned int i = 0; i < forces.size(); ++i)
|
||||
for (unsigned int i = 0; i < forces.size(); ++i)
|
||||
{
|
||||
AiForce *force = &forces[i];
|
||||
AiForce &force = forces[i];
|
||||
// No troops for attacking force
|
||||
if (force->IsAttacking()) {
|
||||
if (force.IsAttacking()) {
|
||||
continue;
|
||||
}
|
||||
if (unit.GroupId == 0 && force->IsBelongsTo(unit.Type)) {
|
||||
force->Insert(unit);
|
||||
if (force.IsBelongsTo(unit.Type)) {
|
||||
force.Insert(unit);
|
||||
unit.GroupId = i + 1;
|
||||
return true;
|
||||
}
|
||||
|
@ -428,11 +416,11 @@ void AiForceManager::CheckUnits(int *counter)
|
|||
// Look through the forces what is missing.
|
||||
for (unsigned int i = 0; i < forces.size(); ++i)
|
||||
{
|
||||
AiForce *force = &forces[i];
|
||||
const AiForce &force = forces[i];
|
||||
|
||||
if (force->State > AI_FORCE_STATE_FREE && force->IsAttacking()) {
|
||||
for (unsigned int j = 0; j < forces[i].Size(); ++j) {
|
||||
const CUnit *unit = forces[i].Units[j];
|
||||
if (force.State > AiForceAttackingState_Free && force.IsAttacking()) {
|
||||
for (unsigned int j = 0; j < force.Size(); ++j) {
|
||||
const CUnit *unit = force.Units[j];
|
||||
attacking[unit->Type->Slot]++;
|
||||
}
|
||||
}
|
||||
|
@ -441,24 +429,24 @@ void AiForceManager::CheckUnits(int *counter)
|
|||
// create missing units
|
||||
for (unsigned int i = 0; i < forces.size(); ++i)
|
||||
{
|
||||
AiForce *force = &forces[i];
|
||||
AiForce &force = forces[i];
|
||||
|
||||
// No troops for attacking force
|
||||
if (force->State == AI_FORCE_STATE_FREE || force->IsAttacking()) {
|
||||
if (force.State == AiForceAttackingState_Free || force.IsAttacking()) {
|
||||
continue;
|
||||
}
|
||||
for (unsigned int j = 0; j < force->UnitTypes.size(); ++j) {
|
||||
const AiUnitType *aiut = &force->UnitTypes[j];
|
||||
const int t = aiut->Type->Slot;
|
||||
const int x = aiut->Want;
|
||||
const int requested = x - (unit_types_count[t] + counter[t] - attacking[t]);
|
||||
for (unsigned int j = 0; j < force.UnitTypes.size(); ++j) {
|
||||
const AiUnitType &aiut = force.UnitTypes[j];
|
||||
const int t = aiut.Type->Slot;
|
||||
const int wantedCount = aiut.Want;
|
||||
const int requested = wantedCount - (unit_types_count[t] + counter[t] - attacking[t]);
|
||||
|
||||
if (requested > 0) { // Request it.
|
||||
AiAddUnitTypeRequest(*aiut->Type, requested);
|
||||
AiAddUnitTypeRequest(*aiut.Type, requested);
|
||||
counter[t] += requested;
|
||||
force->Completed = false;
|
||||
force.Completed = false;
|
||||
}
|
||||
counter[t] -= x;
|
||||
counter[t] -= wantedCount;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -560,7 +548,7 @@ void AiAttackWithForce(unsigned int force)
|
|||
|
||||
/**
|
||||
** Attack opponent with forces.
|
||||
** Merge forces in array into one attack force and attack with it
|
||||
** Merge forces in array into one attack force and attack with it
|
||||
** Merge is make because units in one force help each other during attack
|
||||
**
|
||||
** @param forces Array with Force numbers to attack with (array should be finished with -1).
|
||||
|
@ -611,41 +599,41 @@ void AiAttackWithForces(int *forces)
|
|||
**
|
||||
** @param aiForce force to group.
|
||||
*/
|
||||
static void AiGroupAttackerForTransport(AiForce *aiForce)
|
||||
static void AiGroupAttackerForTransport(AiForce &aiForce)
|
||||
{
|
||||
Assert(aiForce->State == AI_FORCE_STATE_BOARDING);
|
||||
Assert(aiForce.State == AiForceAttackingState_Boarding);
|
||||
|
||||
unsigned int nbToTransport = 0;
|
||||
unsigned int transporterIndex = 0;
|
||||
bool goNext = true;
|
||||
|
||||
for (; transporterIndex < aiForce->Size(); ++transporterIndex) {
|
||||
const CUnit *unit = aiForce->Units[transporterIndex];
|
||||
for (; transporterIndex < aiForce.Size(); ++transporterIndex) {
|
||||
const CUnit *unit = aiForce.Units[transporterIndex];
|
||||
|
||||
if (unit->Type->CanTransport() && unit->Type->MaxOnBoard - unit->BoardCount > 0) {
|
||||
nbToTransport = unit->Type->MaxOnBoard - unit->BoardCount;
|
||||
break;
|
||||
}
|
||||
}
|
||||
if (transporterIndex == aiForce->Size()) {
|
||||
aiForce->State++;
|
||||
if (transporterIndex == aiForce.Size()) {
|
||||
aiForce.State = AiForceAttackingState_Attacking;
|
||||
return ;
|
||||
}
|
||||
for (unsigned int i = 0; i < aiForce->Size(); ++i) {
|
||||
const CUnit &unit = *aiForce->Units[i];
|
||||
const CUnit &transporter = *aiForce->Units[transporterIndex];
|
||||
for (unsigned int i = 0; i < aiForce.Size(); ++i) {
|
||||
const CUnit &unit = *aiForce.Units[i];
|
||||
const CUnit &transporter = *aiForce.Units[transporterIndex];
|
||||
|
||||
if (CanTransport(transporter, unit) && unit.Container == NULL) {
|
||||
goNext = false;
|
||||
}
|
||||
}
|
||||
if (goNext == true) {
|
||||
aiForce->State++;
|
||||
aiForce.State = AiForceAttackingState_Attacking;
|
||||
return ;
|
||||
}
|
||||
for (unsigned int i = 0; i < aiForce->Size(); ++i) {
|
||||
CUnit &unit = *aiForce->Units[i];
|
||||
CUnit &transporter = *aiForce->Units[transporterIndex];
|
||||
for (unsigned int i = 0; i < aiForce.Size(); ++i) {
|
||||
CUnit &unit = *aiForce.Units[i];
|
||||
CUnit &transporter = *aiForce.Units[transporterIndex];
|
||||
|
||||
if (transporter.IsIdle() && unit.CurrentOrder()->GetGoal() == &transporter) {
|
||||
CommandFollow(transporter, unit, 0);
|
||||
|
@ -653,16 +641,16 @@ static void AiGroupAttackerForTransport(AiForce *aiForce)
|
|||
if (CanTransport(transporter, unit) && unit.IsIdle() && unit.Container == NULL) {
|
||||
CommandBoard(unit, transporter, FlushCommands);
|
||||
CommandFollow(transporter, unit, 0);
|
||||
if (--nbToTransport == 0) { // full : nxt transporter.
|
||||
for (++transporterIndex; transporterIndex < aiForce->Size(); ++transporterIndex) {
|
||||
const CUnit &nextTransporter = *aiForce->Units[transporterIndex];
|
||||
if (--nbToTransport == 0) { // full : next transporter.
|
||||
for (++transporterIndex; transporterIndex < aiForce.Size(); ++transporterIndex) {
|
||||
const CUnit &nextTransporter = *aiForce.Units[transporterIndex];
|
||||
|
||||
if (nextTransporter.Type->CanTransport()) {
|
||||
nbToTransport = nextTransporter.Type->MaxOnBoard - nextTransporter.BoardCount;
|
||||
break ;
|
||||
}
|
||||
}
|
||||
if (transporterIndex == aiForce->Size()) { // No more transporter.
|
||||
if (transporterIndex == aiForce.Size()) { // No more transporter.
|
||||
break ;
|
||||
}
|
||||
}
|
||||
|
@ -681,7 +669,7 @@ void AiForce::Update()
|
|||
|
||||
if (Size() == 0) {
|
||||
Attacking = false;
|
||||
if (!Defending && State > 0) {
|
||||
if (!Defending && State > AiForceAttackingState_Waiting) {
|
||||
DebugPrint("%d: Attack force #%lu was destroyed, giving up\n"
|
||||
_C_ AiPlayer->Player->Index _C_ (long unsigned int)(this - &(AiPlayer->Force[0])));
|
||||
Reset(true);
|
||||
|
@ -698,7 +686,7 @@ void AiForce::Update()
|
|||
}
|
||||
}
|
||||
if (Attacking == false) {
|
||||
if (!Defending && State > 0) {
|
||||
if (!Defending && State > AiForceAttackingState_Waiting) {
|
||||
DebugPrint("%d: Attack force #%lu has lost all agresive units, giving up\n"
|
||||
_C_ AiPlayer->Player->Index _C_ (long unsigned int)(this - &(AiPlayer->Force[0])));
|
||||
Reset(true);
|
||||
|
@ -707,31 +695,30 @@ void AiForce::Update()
|
|||
}
|
||||
|
||||
#if 0
|
||||
if (State == AI_FORCE_STATE_WAITING) {
|
||||
if (!AiPlanAttack(force)) {
|
||||
if (State == AiForceAttackingState_Waiting) {
|
||||
if (!this->PlanAttack()) {
|
||||
DebugPrint("Can't transport, look for walls\n");
|
||||
if (!AiFindWall(force)) {
|
||||
if (!AiFindWall(this)) {
|
||||
Attacking = false;
|
||||
return ;
|
||||
}
|
||||
}
|
||||
State = AI_FORCE_STATE_BOARDING;
|
||||
State = AiForceAttackingState_Boarding;
|
||||
}
|
||||
#endif
|
||||
|
||||
if (State == AI_FORCE_STATE_BOARDING) {
|
||||
AiGroupAttackerForTransport(this);
|
||||
if (State == AiForceAttackingState_Boarding) {
|
||||
AiGroupAttackerForTransport(*this);
|
||||
return ;
|
||||
}
|
||||
|
||||
|
||||
// Find a unit that isn't idle
|
||||
unit = NoUnitP;
|
||||
if (State == AI_FORCE_STATE_ATTACKING) {
|
||||
if (State == AiForceAttackingState_Attacking) {
|
||||
for (unsigned int i = 0; i < Size(); ++i) {
|
||||
CUnit *aiunit = Units[i];
|
||||
if (!aiunit->IsIdle()) {
|
||||
// Found an idle unit, use it if we find nothing better
|
||||
// Found an no-idle unit, use it if we find nothing better
|
||||
if (unit == NoUnitP) {
|
||||
unit = aiunit;
|
||||
}
|
||||
|
@ -772,44 +759,8 @@ void AiForce::Update()
|
|||
}
|
||||
} else { // Everyone is idle, find a new target
|
||||
Vec2i pos;
|
||||
//FIXME: rb - I don't know if AI can use transport now
|
||||
#if 0
|
||||
if (State == AI_FORCE_STATE_ATTACKING) {
|
||||
unit = NULL;
|
||||
|
||||
for (unsigned int i = 0; i < Units.size(); ++i) {
|
||||
CUnit *aiunit = Units[i];
|
||||
if (aiunit->Type->CanAttack) {
|
||||
unit = AttackUnitsInDistance(aiunit, MaxMapWidth);
|
||||
break;
|
||||
}
|
||||
}
|
||||
if (!unit) {
|
||||
// No enemy found, give up
|
||||
// FIXME: should the force go home or keep trying to attack?
|
||||
DebugPrint("Attack force can't find a target, giving up\n");
|
||||
Attacking = false;
|
||||
return;
|
||||
}
|
||||
pos = unit->tilePos;
|
||||
} else {
|
||||
pos = this->GoalPos;
|
||||
}
|
||||
for (unsigned int i = 0; i < Units.size(); ++i) {
|
||||
CUnit *aiunit = Units[i];
|
||||
|
||||
if (aiunit->Type->CanTransport() && aiunit->BoardCount > 0) {
|
||||
CommandUnload(aiunit, pos, NULL, FlushCommands);
|
||||
} else if (aiunit->Type->CanAttack) {
|
||||
CommandAttack(aiunit, pos, NULL, FlushCommands);
|
||||
} else if (force->State == 2) {
|
||||
CommandMove(aiunit, pos, FlushCommands);
|
||||
}
|
||||
}
|
||||
force->State = 3;
|
||||
#else
|
||||
if (State == AI_FORCE_STATE_ATTACKING) {
|
||||
|
||||
if (State == AiForceAttackingState_Attacking) {
|
||||
unit = AiForceEnemyFinder<false>(this).enemy;
|
||||
|
||||
if (!unit) {
|
||||
|
@ -825,7 +776,6 @@ void AiForce::Update()
|
|||
pos = this->GoalPos;
|
||||
}
|
||||
AiForceAttackSender(this, pos);
|
||||
#endif
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -833,30 +783,30 @@ void AiForceManager::Update()
|
|||
{
|
||||
for(unsigned int f = 0; f < forces.size(); ++f)
|
||||
{
|
||||
AiForce *force = &forces[f];
|
||||
AiForce &force = forces[f];
|
||||
//
|
||||
// Look if our defenders still have enemies in range.
|
||||
//
|
||||
if (force->Defending) {
|
||||
force->Clean();
|
||||
if (force.Defending) {
|
||||
force.Clean();
|
||||
//
|
||||
// Look if still enemies in attack range.
|
||||
//
|
||||
if(!AiForceEnemyFinder<true>(force).found()) {
|
||||
if(!AiForceEnemyFinder<true>(&force).found()) {
|
||||
DebugPrint("%d:FIXME: not written, should send force #%d home\n"
|
||||
_C_ AiPlayer->Player->Index _C_ f);
|
||||
force->Defending = false;
|
||||
force->Attacking = false;
|
||||
force.Defending = false;
|
||||
force.Attacking = false;
|
||||
}
|
||||
} else if (force->Attacking) {
|
||||
force->Clean();
|
||||
force->Update();
|
||||
} else if (force.Attacking) {
|
||||
force.Clean();
|
||||
force.Update();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
** Entry point of force manager, perodic called.
|
||||
** Entry point of force manager, periodic called.
|
||||
**
|
||||
** @todo FIXME: is this really needed anymore
|
||||
*/
|
||||
|
|
|
@ -60,14 +60,7 @@ public:
|
|||
std::string Name; /// Name of this ai
|
||||
std::string Race; /// for this race
|
||||
std::string Class; /// class of this ai
|
||||
|
||||
#if 0
|
||||
// nice flags
|
||||
unsigned char AllExplored : 1; /// Ai sees unexplored area
|
||||
unsigned char AllVisbile : 1; /// Ai sees invisibile area
|
||||
#endif
|
||||
|
||||
std::string Script; /// Main script
|
||||
std::string Script; /// Main script
|
||||
};
|
||||
|
||||
/**
|
||||
|
@ -89,7 +82,7 @@ public:
|
|||
AiUnitType() : Want(0), Type(NULL) {}
|
||||
|
||||
unsigned int Want; /// number of this unit-type wanted
|
||||
CUnitType *Type; /// unit-type self
|
||||
CUnitType *Type; /// unit-type self
|
||||
};
|
||||
|
||||
/**
|
||||
|
@ -100,11 +93,13 @@ enum AiForceRole {
|
|||
AiForceRoleDefend /// Force should defend
|
||||
};
|
||||
|
||||
#define AI_FORCE_STATE_FREE -1
|
||||
#define AI_FORCE_STATE_WAITING 0
|
||||
#define AI_FORCE_STATE_BOARDING 1
|
||||
//#define AI_FORCE_STATE_OERATIONAL 2
|
||||
#define AI_FORCE_STATE_ATTACKING 3
|
||||
enum AiForceAttackingState
|
||||
{
|
||||
AiForceAttackingState_Free = -1,
|
||||
AiForceAttackingState_Waiting = 0,
|
||||
AiForceAttackingState_Boarding,
|
||||
AiForceAttackingState_Attacking,
|
||||
};
|
||||
|
||||
/**
|
||||
** Define an AI force.
|
||||
|
@ -113,19 +108,10 @@ enum AiForceRole {
|
|||
*/
|
||||
class AiForce {
|
||||
friend class AiForceManager;
|
||||
|
||||
bool IsBelongsTo(const CUnitType *type);
|
||||
void Insert(CUnit &unit)
|
||||
{
|
||||
Units.Insert(&unit);
|
||||
unit.RefsIncrease();
|
||||
}
|
||||
|
||||
void Update();
|
||||
public:
|
||||
AiForce() : Completed(false), Defending(false), Attacking(false),
|
||||
Role(0), State(AI_FORCE_STATE_FREE),
|
||||
MustTransport(false)
|
||||
AiForce() :
|
||||
Completed(false), Defending(false), Attacking(false),
|
||||
Role(0), State(AiForceAttackingState_Free)
|
||||
{
|
||||
GoalPos.x = GoalPos.y = 0;
|
||||
}
|
||||
|
@ -133,8 +119,7 @@ public:
|
|||
void Remove(CUnit &unit)
|
||||
{
|
||||
if (Units.Remove(&unit)) {
|
||||
unit.GroupId = 0;
|
||||
unit.RefsDecrease();
|
||||
InternalRemoveUnit(&unit);
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -147,13 +132,13 @@ public:
|
|||
Attacking = false;
|
||||
if (types) {
|
||||
UnitTypes.clear();
|
||||
State = AI_FORCE_STATE_FREE;
|
||||
State = AiForceAttackingState_Free;
|
||||
} else {
|
||||
State = AI_FORCE_STATE_WAITING;
|
||||
State = AiForceAttackingState_Waiting;
|
||||
}
|
||||
Units.for_each(InternalRemoveUnit);
|
||||
Units.clear();
|
||||
GoalPos.x = GoalPos.y = 0;
|
||||
MustTransport = false;
|
||||
}
|
||||
inline size_t Size() const
|
||||
{
|
||||
|
@ -165,39 +150,51 @@ public:
|
|||
return (!Defending && Attacking);
|
||||
}
|
||||
|
||||
void CountTypes(unsigned int *counter, const size_t len);
|
||||
void Attack(const Vec2i &pos);
|
||||
void Clean();
|
||||
int PlanAttack();
|
||||
|
||||
private:
|
||||
void CountTypes(unsigned int *counter, const size_t len);
|
||||
bool IsBelongsTo(const CUnitType *type);
|
||||
void Insert(CUnit &unit)
|
||||
{
|
||||
Units.Insert(&unit);
|
||||
unit.RefsIncrease();
|
||||
}
|
||||
|
||||
void Update();
|
||||
|
||||
static void InternalRemoveUnit(CUnit *unit) {
|
||||
unit->GroupId = 0;
|
||||
unit->RefsDecrease();
|
||||
}
|
||||
|
||||
public:
|
||||
bool Completed; /// Flag saying force is complete build
|
||||
bool Defending; /// Flag saying force is defending
|
||||
bool Attacking; /// Flag saying force is attacking
|
||||
char Role; /// Role of the force
|
||||
|
||||
std::vector<AiUnitType> UnitTypes; /// Count and types of unit-type
|
||||
CUnitCache Units; /// Units in the force
|
||||
CUnitCache Units; /// Units in the force
|
||||
|
||||
//
|
||||
// If attacking
|
||||
//
|
||||
int State;/// Attack state
|
||||
AiForceAttackingState State; /// Attack state
|
||||
Vec2i GoalPos; /// Attack point tile map position
|
||||
bool MustTransport;/// Flag must use transporter
|
||||
|
||||
void Attack(const Vec2i &pos);
|
||||
void Clean();
|
||||
int PlanAttack();
|
||||
};
|
||||
|
||||
// forces
|
||||
#define AI_MAX_FORCES 10 /// How many forces are supported
|
||||
//#define AI_MAX_ATTACKING_FORCES 30 /// Attacking forces (max supported 32)
|
||||
|
||||
/**
|
||||
** AI force manager.
|
||||
**
|
||||
** A Forces container for the force manager to handle
|
||||
*/
|
||||
class AiForceManager {
|
||||
std::vector<AiForce> forces;
|
||||
char script[AI_MAX_FORCES];
|
||||
public:
|
||||
AiForceManager();
|
||||
|
||||
|
@ -217,7 +214,6 @@ public:
|
|||
return -1;
|
||||
}
|
||||
|
||||
|
||||
inline unsigned int getScriptForce(unsigned int index) {
|
||||
if (script[index] == -1) {
|
||||
script[index] = FindFreeForce();
|
||||
|
@ -230,6 +226,9 @@ public:
|
|||
void Update();
|
||||
unsigned int FindFreeForce(int role = AiForceRoleAttack);
|
||||
void CheckUnits(int *counter);
|
||||
private:
|
||||
std::vector<AiForce> forces;
|
||||
char script[AI_MAX_FORCES];
|
||||
};
|
||||
|
||||
/**
|
||||
|
@ -241,12 +240,13 @@ class AiBuildQueue {
|
|||
public:
|
||||
AiBuildQueue() : Want(0), Made(0), Type(NULL), Wait(0), X(-1), Y(-1) {}
|
||||
|
||||
public:
|
||||
unsigned int Want; /// requested number
|
||||
unsigned int Made; /// built number
|
||||
CUnitType *Type; /// unit-type
|
||||
unsigned long Wait; /// wait until this cycle
|
||||
short int X; /// build near x pos on map
|
||||
short int Y; /// build near y pos on map
|
||||
short int X; /// build near x pos on map
|
||||
short int Y; /// build near y pos on map
|
||||
};
|
||||
|
||||
/**
|
||||
|
@ -256,6 +256,7 @@ class AiExplorationRequest {
|
|||
public:
|
||||
AiExplorationRequest(const Vec2i& pos, int mask) : pos(pos), Mask(mask) { }
|
||||
|
||||
public:
|
||||
Vec2i pos; /// pos on map
|
||||
int Mask; /// mask ( ex: MapFieldLandUnit )
|
||||
};
|
||||
|
@ -267,6 +268,7 @@ class AiTransportRequest {
|
|||
public:
|
||||
AiTransportRequest() : Unit(NULL) {}
|
||||
|
||||
public:
|
||||
CUnit *Unit;
|
||||
CUnit::COrder Order;
|
||||
};
|
||||
|
@ -279,7 +281,7 @@ public:
|
|||
PlayerAi() : Player(NULL), AiType(NULL),
|
||||
SleepCycles(0), NeededMask(0), NeedSupply(false),
|
||||
ScriptDebug(false), LastExplorationGameCycle(0),
|
||||
LastCanNotMoveGameCycle(0), LastRepairBuilding(0)
|
||||
LastCanNotMoveGameCycle(0), LastRepairBuilding(0)
|
||||
{
|
||||
memset(Reserve, 0, sizeof(Reserve));
|
||||
memset(Used, 0, sizeof(Used));
|
||||
|
@ -288,13 +290,14 @@ public:
|
|||
memset(TriedRepairWorkers, 0, sizeof(TriedRepairWorkers));
|
||||
}
|
||||
|
||||
public:
|
||||
CPlayer *Player; /// Engine player structure
|
||||
CAiType *AiType; /// AI type of this player AI
|
||||
// controller
|
||||
std::string Script; /// Script executed
|
||||
unsigned long SleepCycles; /// Cycles to sleep
|
||||
|
||||
AiForceManager Force; /// Forces controlled by AI
|
||||
AiForceManager Force; /// Forces controlled by AI
|
||||
|
||||
// resource manager
|
||||
int Reserve[MaxCosts]; /// Resources to keep in reserve
|
||||
|
@ -314,7 +317,7 @@ public:
|
|||
std::vector<CUpgrade *> ResearchRequests; /// Upgrades requested and priority list
|
||||
std::vector<AiBuildQueue> UnitTypeBuilt; /// What the resource manager should build
|
||||
int LastRepairBuilding; /// Last building checked for repair in this turn
|
||||
unsigned int TriedRepairWorkers[UnitMax]; /// No. workers that failed trying to repair a building
|
||||
unsigned int TriedRepairWorkers[UnitMax]; /// No. workers that failed trying to repair a building
|
||||
};
|
||||
|
||||
/**
|
||||
|
@ -373,8 +376,6 @@ public:
|
|||
** units/buildings/mines which can store this resource.
|
||||
*/
|
||||
std::vector<std::vector<CUnitType *> > Depots;
|
||||
|
||||
|
||||
};
|
||||
|
||||
/*----------------------------------------------------------------------------
|
||||
|
|
|
@ -33,17 +33,11 @@
|
|||
-- Includes
|
||||
----------------------------------------------------------------------------*/
|
||||
|
||||
#include <stdio.h>
|
||||
#include <stdlib.h>
|
||||
|
||||
#include "stratagus.h"
|
||||
#include "unittype.h"
|
||||
#include "unit.h"
|
||||
#include "spells.h"
|
||||
#include "actions.h"
|
||||
#include "map.h"
|
||||
#include "ai_local.h"
|
||||
#include "player.h"
|
||||
|
||||
/*----------------------------------------------------------------------------
|
||||
-- Functions
|
||||
|
@ -55,9 +49,9 @@
|
|||
*/
|
||||
void AiCheckMagic()
|
||||
{
|
||||
const int n = AiPlayer->Player->TotalNumUnits;
|
||||
CUnit **units = AiPlayer->Player->Units;
|
||||
const CPlayer &player = *AiPlayer->Player; /*units[0]->Player */
|
||||
CPlayer &player = *AiPlayer->Player;
|
||||
const int n = player.TotalNumUnits;
|
||||
CUnit **units = player.Units;
|
||||
|
||||
for (int i = 0; i < n; ++i) {
|
||||
CUnit &unit = *units[i];
|
||||
|
|
|
@ -43,7 +43,6 @@
|
|||
#include "pathfinder.h"
|
||||
#include "actions.h"
|
||||
#include "ai_local.h"
|
||||
#include "player.h"
|
||||
|
||||
/*----------------------------------------------------------------------------
|
||||
-- Variables
|
||||
|
@ -433,7 +432,7 @@ int AiFindWall(AiForce *force)
|
|||
delete[] points;
|
||||
|
||||
if (dest.x != -1) {
|
||||
force->State = AI_FORCE_STATE_WAITING;
|
||||
force->State = AiForceAttackingState_Waiting;
|
||||
for (unsigned int i = 0; i < force->Units.size(); ++i) {
|
||||
CUnit &aiunit = *force->Units[i];
|
||||
if (aiunit.Type->CanAttack) {
|
||||
|
@ -460,20 +459,16 @@ int AiFindWall(AiForce *force)
|
|||
*/
|
||||
int AiForce::PlanAttack()
|
||||
{
|
||||
unsigned char *watermatrix;
|
||||
int state;
|
||||
CUnit *transporter;
|
||||
|
||||
DebugPrint("%d: Planning for force #%lu of player #%d\n"_C_ AiPlayer->Player->Index
|
||||
_C_ (long unsigned int)(this - &(AiPlayer->Force[0])) _C_ AiPlayer->Player->Index);
|
||||
|
||||
watermatrix = CreateMatrix();
|
||||
unsigned char *watermatrix = CreateMatrix();
|
||||
|
||||
//
|
||||
// Transporter must be already assigned to the force.
|
||||
// NOTE: finding free transportes was too much work for me.
|
||||
// NOTE: finding free transporters was too much work for me.
|
||||
//
|
||||
state = 1;
|
||||
int state = 1;
|
||||
for (unsigned int i = 0; i < Size(); ++i) {
|
||||
const CUnit &aiunit = *Units[i];
|
||||
|
||||
|
@ -487,7 +482,7 @@ int AiForce::PlanAttack()
|
|||
//
|
||||
// No transport that belongs to the force.
|
||||
//
|
||||
transporter = NULL;
|
||||
CUnit *transporter = NULL;
|
||||
if (state) {
|
||||
for (int i = 0; i < AiPlayer->Player->TotalNumUnits; ++i) {
|
||||
CUnit &unit = *AiPlayer->Player->Units[i];
|
||||
|
@ -572,9 +567,7 @@ int AiForce::PlanAttack()
|
|||
}
|
||||
DebugPrint("%d: Can attack\n" _C_ AiPlayer->Player->Index);
|
||||
GoalPos = pos;
|
||||
MustTransport = state == 2;
|
||||
|
||||
State = AI_FORCE_STATE_BOARDING;
|
||||
State = AiForceAttackingState_Boarding;
|
||||
return 1;
|
||||
}
|
||||
return 0;
|
||||
|
|
|
@ -977,21 +977,13 @@ static int CmpWorkers(const void *w0,const void *w1) {
|
|||
*/
|
||||
static void AiCollectResources()
|
||||
{
|
||||
CUnit *units_with_resource[MaxCosts][UnitMax]; // Worker with resource
|
||||
CUnit *units_assigned[MaxCosts][UnitMax]; // Worker assigned to resource
|
||||
CUnit *units_unassigned[MaxCosts][UnitMax]; // Unassigned workers
|
||||
int num_units_with_resource[MaxCosts];
|
||||
int num_units_assigned[MaxCosts];
|
||||
int num_units_unassigned[MaxCosts];
|
||||
int c;
|
||||
int src_c;
|
||||
int i;
|
||||
int j;
|
||||
int k;
|
||||
int n;
|
||||
CUnit **units;
|
||||
int percent[MaxCosts];
|
||||
int percent_total;
|
||||
|
||||
int priority_resource[MaxCosts];
|
||||
int priority_needed[MaxCosts];
|
||||
|
@ -1007,19 +999,17 @@ static void AiCollectResources()
|
|||
//
|
||||
total_harvester = 0;
|
||||
|
||||
n = AiPlayer->Player->TotalNumUnits;
|
||||
const int n = AiPlayer->Player->TotalNumUnits;
|
||||
units = AiPlayer->Player->Units;
|
||||
for (i = 0; i < n; ++i) {
|
||||
for (int i = 0; i < n; ++i) {
|
||||
CUnit &unit = *units[i];
|
||||
if (!unit.Type->Harvester) {
|
||||
continue;
|
||||
}
|
||||
|
||||
c = unit.CurrentResource;
|
||||
const int c = unit.CurrentResource;
|
||||
|
||||
//
|
||||
// See if it's assigned already
|
||||
//
|
||||
if (c && unit.OrderCount == 1 &&
|
||||
unit.CurrentAction() == UnitActionResource) {
|
||||
units_assigned[c][num_units_assigned[c]++] = &unit;
|
||||
|
@ -1027,27 +1017,21 @@ static void AiCollectResources()
|
|||
continue;
|
||||
}
|
||||
|
||||
//
|
||||
// Ignore busy units. ( building, fighting, ... )
|
||||
//
|
||||
if (!unit.IsIdle()) {
|
||||
continue;
|
||||
}
|
||||
|
||||
//
|
||||
// Send workers with resources back home.
|
||||
//
|
||||
if (unit.ResourcesHeld && c) {
|
||||
units_with_resource[c][num_units_with_resource[c]++] = &unit;
|
||||
num_units_with_resource[c]++;
|
||||
CommandReturnGoods(unit, 0, FlushCommands);
|
||||
total_harvester++;
|
||||
continue;
|
||||
}
|
||||
|
||||
//
|
||||
// Look what the unit can do
|
||||
//
|
||||
for (c = 1; c < MaxCosts; ++c) {
|
||||
for (int c = 1; c < MaxCosts; ++c) {
|
||||
if (unit.Type->ResInfo[c]) {
|
||||
units_unassigned[c][num_units_unassigned[c]++] = &unit;
|
||||
}
|
||||
|
@ -1055,14 +1039,14 @@ static void AiCollectResources()
|
|||
++total_harvester;
|
||||
}
|
||||
|
||||
if(!total_harvester) {
|
||||
if (!total_harvester) {
|
||||
return;
|
||||
}
|
||||
|
||||
memset(wanted, 0, sizeof(wanted));
|
||||
|
||||
percent_total = 100;
|
||||
for (c = 1; c < MaxCosts; ++c) {
|
||||
int percent_total = 100;
|
||||
for (int c = 1; c < MaxCosts; ++c) {
|
||||
percent[c] = AiPlayer->Collect[c];
|
||||
if ((AiPlayer->NeededMask & (1 << c))) { // Double percent if needed
|
||||
percent_total += percent[c];
|
||||
|
@ -1070,11 +1054,9 @@ static void AiCollectResources()
|
|||
}
|
||||
}
|
||||
|
||||
//
|
||||
// Turn percent values into harvester numbers.
|
||||
//
|
||||
for (c = 1; c < MaxCosts; ++c ) {
|
||||
if(percent[c]) {
|
||||
for (int c = 1; c < MaxCosts; ++c ) {
|
||||
if (percent[c]) {
|
||||
// Wanted needs to be representative.
|
||||
if (total_harvester < 5) {
|
||||
wanted[c] = 1 + (percent[c] * 5) / percent_total;
|
||||
|
@ -1084,67 +1066,55 @@ static void AiCollectResources()
|
|||
}
|
||||
}
|
||||
|
||||
//
|
||||
// Initialise priority & mapping
|
||||
//
|
||||
for (c = 0; c < MaxCosts; ++c) {
|
||||
for (int c = 0; c < MaxCosts; ++c) {
|
||||
priority_resource[c] = c;
|
||||
priority_needed[c] = wanted[c] - num_units_assigned[c] - num_units_with_resource[c];
|
||||
|
||||
if (c && num_units_assigned[c] > 1) {
|
||||
//first should go workers with lower ResourcesHeld value
|
||||
qsort(units_assigned[c], num_units_assigned[c],
|
||||
sizeof(CUnit*), CmpWorkers);
|
||||
qsort(units_assigned[c], num_units_assigned[c], sizeof(CUnit*), CmpWorkers);
|
||||
}
|
||||
|
||||
}
|
||||
CUnit* unit;
|
||||
do {
|
||||
//
|
||||
// sort resources by priority
|
||||
//
|
||||
for (i = 0; i < MaxCosts; ++i) {
|
||||
for (j = i + 1; j < MaxCosts; ++j) {
|
||||
for (int i = 0; i < MaxCosts; ++i) {
|
||||
for (int j = i + 1; j < MaxCosts; ++j) {
|
||||
if (priority_needed[j] > priority_needed[i]) {
|
||||
c = priority_needed[j];
|
||||
priority_needed[j] = priority_needed[i];
|
||||
priority_needed[i] = c;
|
||||
c = priority_resource[j];
|
||||
priority_resource[j] = priority_resource[i];
|
||||
priority_resource[i] = c;
|
||||
std::swap(priority_needed[i], priority_needed[j]);
|
||||
std::swap(priority_resource[i], priority_resource[j]);
|
||||
}
|
||||
}
|
||||
}
|
||||
unit = NoUnitP;
|
||||
//
|
||||
// Try to complete each ressource in the priority order
|
||||
//
|
||||
|
||||
for (i = 0; i < MaxCosts; ++i) {
|
||||
c = priority_resource[i];
|
||||
// Try to complete each ressource in the priority order
|
||||
for (int i = 0; i < MaxCosts; ++i) {
|
||||
int c = priority_resource[i];
|
||||
|
||||
//
|
||||
// If there is a free worker for c, take it.
|
||||
//
|
||||
if (num_units_unassigned[c]) {
|
||||
// Take the unit.
|
||||
j = 0;
|
||||
while (j < num_units_unassigned[c] && !AiAssignHarvester(*units_unassigned[c][j], c)) {
|
||||
while (0 < num_units_unassigned[c] && !AiAssignHarvester(*units_unassigned[c][0], c)) {
|
||||
// can't assign to c => remove from units_unassigned !
|
||||
units_unassigned[c][j] = units_unassigned[c][--num_units_unassigned[c]];
|
||||
units_unassigned[c][0] = units_unassigned[c][--num_units_unassigned[c]];
|
||||
}
|
||||
|
||||
// unit is assigned
|
||||
if (j < num_units_unassigned[c]) {
|
||||
unit = units_unassigned[c][j];
|
||||
units_unassigned[c][j] = units_unassigned[c][--num_units_unassigned[c]];
|
||||
if (0 < num_units_unassigned[c]) {
|
||||
unit = units_unassigned[c][0];
|
||||
units_unassigned[c][0] = units_unassigned[c][--num_units_unassigned[c]];
|
||||
|
||||
// remove it from other ressources
|
||||
for (j = 0; j < MaxCosts; ++j) {
|
||||
for (int j = 0; j < MaxCosts; ++j) {
|
||||
if (j == c || !unit->Type->ResInfo[j]) {
|
||||
continue;
|
||||
}
|
||||
for (k = 0; k < num_units_unassigned[j]; ++k) {
|
||||
for (int k = 0; k < num_units_unassigned[j]; ++k) {
|
||||
if (units_unassigned[j][k] == unit) {
|
||||
units_unassigned[j][k] = units_unassigned[j][--num_units_unassigned[j]];
|
||||
break;
|
||||
|
@ -1159,9 +1129,9 @@ static void AiCollectResources()
|
|||
//
|
||||
if (!unit) {
|
||||
// Take from lower priority only (i+1).
|
||||
for (j = i + 1; j < MaxCosts && !unit; ++j) {
|
||||
for (int j = i + 1; j < MaxCosts && !unit; ++j) {
|
||||
// Try to move worker from src_c to c
|
||||
src_c = priority_resource[j];
|
||||
const int src_c = priority_resource[j];
|
||||
|
||||
// Don't complete with lower priority ones...
|
||||
if (wanted[src_c] > wanted[c] ||
|
||||
|
@ -1170,7 +1140,7 @@ static void AiCollectResources()
|
|||
continue;
|
||||
}
|
||||
|
||||
for (k = num_units_assigned[src_c] - 1; k >= 0 && !unit; --k) {
|
||||
for (int k = num_units_assigned[src_c] - 1; k >= 0 && !unit; --k) {
|
||||
unit = units_assigned[src_c][k];
|
||||
|
||||
if (unit->SubAction >= 65 /* SUB_STOP_GATHERING */ ) {
|
||||
|
@ -1334,7 +1304,6 @@ static int AiRepairUnit(CUnit &unit)
|
|||
}
|
||||
}
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
|
@ -1343,25 +1312,20 @@ static int AiRepairUnit(CUnit &unit)
|
|||
*/
|
||||
static void AiCheckRepair()
|
||||
{
|
||||
int i;
|
||||
int j;
|
||||
int k;
|
||||
int n;
|
||||
bool repair_flag;
|
||||
const int n = AiPlayer->Player->TotalNumUnits;
|
||||
int k = 0;
|
||||
|
||||
n = AiPlayer->Player->TotalNumUnits;
|
||||
k = 0;
|
||||
// Selector for next unit
|
||||
for (i = n - 1; i >= 0; --i) {
|
||||
for (int i = n - 1; i >= 0; --i) {
|
||||
CUnit *unit = AiPlayer->Player->Units[i];
|
||||
if (unit && UnitNumber(*unit) == AiPlayer->LastRepairBuilding) {
|
||||
k = i + 1;
|
||||
}
|
||||
}
|
||||
|
||||
for (i = k; i < n; ++i) {
|
||||
for (int i = k; i < n; ++i) {
|
||||
CUnit &unit = *AiPlayer->Player->Units[i];
|
||||
repair_flag = true;
|
||||
bool repair_flag = true;
|
||||
|
||||
if (!unit.IsAliveOnMap()) {
|
||||
continue;
|
||||
|
@ -1374,7 +1338,6 @@ static void AiCheckRepair()
|
|||
unit.CurrentAction() != UnitActionUpgradeTo &&
|
||||
unit.Variable[HP_INDEX].Value < unit.Variable[HP_INDEX].Max &&
|
||||
unit.Attacked + 5 * CYCLES_PER_SECOND < GameCycle) {
|
||||
|
||||
//
|
||||
// FIXME: Repair only units under control
|
||||
//
|
||||
|
@ -1384,7 +1347,7 @@ static void AiCheckRepair()
|
|||
//
|
||||
// Must check, if there are enough resources
|
||||
//
|
||||
for (j = 1; j < MaxCosts; ++j) {
|
||||
for (int j = 1; j < MaxCosts; ++j) {
|
||||
if (unit.Stats->Costs[j] &&
|
||||
AiPlayer->Player->Resources[j] < 99) {
|
||||
repair_flag = false;
|
||||
|
|
|
@ -1420,7 +1420,7 @@ static int CclDefineAiPlayer(lua_State *l)
|
|||
lua_pop(l, 1);
|
||||
} else if (!strcmp(value, "state")) {
|
||||
lua_rawgeti(l, j + 1, k + 1);
|
||||
ai->Force[i].State = LuaToNumber(l, -1);
|
||||
ai->Force[i].State = AiForceAttackingState(LuaToNumber(l, -1));
|
||||
lua_pop(l, 1);
|
||||
} else if (!strcmp(value, "goalx")) {
|
||||
lua_rawgeti(l, j + 1, k + 1);
|
||||
|
@ -1431,9 +1431,7 @@ static int CclDefineAiPlayer(lua_State *l)
|
|||
ai->Force[i].GoalPos.y = LuaToNumber(l, -1);
|
||||
lua_pop(l, 1);
|
||||
} else if (!strcmp(value, "must-transport")) {
|
||||
lua_rawgeti(l, j + 1, k + 1);
|
||||
ai->Force[i].MustTransport = LuaToNumber(l, -1) ? true : false;
|
||||
lua_pop(l, 1);
|
||||
// Keep for backward compatibility
|
||||
} else {
|
||||
LuaError(l, "Unsupported tag: %s" _C_ value);
|
||||
}
|
||||
|
|
Loading…
Add table
Reference in a new issue