From 941c1731931ead811abdbb1e4d9da99069303c86 Mon Sep 17 00:00:00 2001 From: Joris <joris.dauphin@gmail.com> Date: Sat, 5 May 2012 05:15:22 +0200 Subject: [PATCH] Manage Attack with transporter --- src/ai/ai_force.cpp | 119 +++++++++++--------------------------------- 1 file changed, 28 insertions(+), 91 deletions(-) diff --git a/src/ai/ai_force.cpp b/src/ai/ai_force.cpp index dfaec0f08..2877d49b6 100644 --- a/src/ai/ai_force.cpp +++ b/src/ai/ai_force.cpp @@ -86,52 +86,6 @@ private: const CUnit **enemy; }; -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 &aiForce = AiPlayer->Force[force]; - - aiForce.Attacking = true; - aiForce.State = AiForceAttackingState_Attacking; - aiForce.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); - } - - void operator()(CUnit *const unit) const { - // this may be problem if units are in bunker and we want sent - // them to attack - if (unit->Container == NULL) { - // To avoid lot of CPU consuption, send them with a small time difference. - unit->Wait = delta; - ++delta; - if (unit->Type->CanTransport() && unit->BoardCount > 0) { - CommandUnload(*unit, goalPos, NULL, FlushCommands); - } else if (unit->Type->CanAttack) { - CommandAttack(*unit, goalPos, NULL, FlushCommands); - } else { - CommandMove(*unit, goalPos, FlushCommands); - } - } - } - -private: - Vec2i goalPos; - mutable int delta; -}; - - - /*---------------------------------------------------------------------------- -- Variables ----------------------------------------------------------------------------*/ @@ -322,7 +276,7 @@ void AiForce::Attack(const Vec2i &pos) } Attacking = true; - if (goalPos.x == -1 || goalPos.y == -1) { + if (Map.Info.IsPointOnMap(goalPos) == false) { /* Search in entire map */ const CUnit *enemy = NULL; AiForceEnemyFinder<false>(*this, &enemy); @@ -331,7 +285,7 @@ void AiForce::Attack(const Vec2i &pos) } } this->GoalPos = goalPos; - if (goalPos.x == -1 || goalPos.y == -1) { + if (Map.Info.IsPointOnMap(goalPos) == false) { 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); @@ -340,7 +294,7 @@ void AiForce::Attack(const Vec2i &pos) return; } // Send all units in the force to enemy. - AiForceAttackSender(this, goalPos); + this->State = AiForceAttackingState_Attacking; } AiForceManager::AiForceManager() @@ -706,58 +660,41 @@ void AiForce::Update() AiGroupAttackerForTransport(*this); return ; } - // Find a unit that is attacking - const CUnit *unit = NoUnitP; - if (State == AiForceAttackingState_Attacking) { - for (unsigned int i = 0; i < Size(); ++i) { - CUnit &aiunit = *Units[i]; - if (aiunit.CurrentAction() == UnitActionAttack) { - unit = &aiunit; - break; + std::vector<CUnit *> idleUnits; + const CUnit *leader = NULL; + for (unsigned int i = 0; i != Size(); ++i) { + CUnit &aiunit = *Units[i]; + + if (aiunit.IsIdle()) { + if (aiunit.IsAliveOnMap()) { + idleUnits.push_back(&aiunit); } + } else if (aiunit.CurrentAction() == UnitActionAttack) { + leader = &aiunit; + } else if (leader == NULL) { + leader = &aiunit; } } - if (unit != NULL) { - Assert(unit->CurrentAction() == UnitActionAttack); - // Give idle units a new goal - // FIXME: may not be a good goal - const Vec2i &pos = unit->pathFinderData->input.GetGoalPos(); + const Vec2i pos = leader != NULL ? leader->tilePos : this->GoalPos; + for (size_t i = 0; i != idleUnits.size(); ++i) { + CUnit &aiunit = *idleUnits[i]; + const int delay = i / 5; // To avoid lot of CPU consuption, send them with a small time difference. - for (unsigned int i = 0; i < Size(); ++i) { - CUnit &aiunit = *Units[i]; - - if (!aiunit.IsIdle()) { - continue; - } - if (aiunit.Type->CanAttack) { - CommandAttack(aiunit, pos, NULL, FlushCommands); - } else if (aiunit.Type->CanTransport()) { + aiunit.Wait = delay; + if (aiunit.Type->CanAttack) { + CommandAttack(aiunit, pos, NULL, FlushCommands); + } else if (aiunit.Type->CanTransport()) { + if (aiunit.BoardCount != 0) { + CommandUnload(aiunit, pos, NULL, FlushCommands); + } else { // FIXME : Retrieve unit blocked (transport previously full) CommandMove(aiunit, aiunit.Player->StartPos, FlushCommands); - } else { - CommandMove(aiunit, pos, FlushCommands); + this->Remove(aiunit); } - } - } else { // Everyone is idle, find a new target - Vec2i pos; - - if (State == AiForceAttackingState_Attacking) { - AiForceEnemyFinder<false>(*this, &unit); - - if (!unit) { - // No enemy found, give up - // FIXME: should the force go home or keep trying to attack? - DebugPrint("%d: Attack force #%lu can't find a target, giving up\n" - _C_ AiPlayer->Player->Index _C_(long unsigned int)(this - & (AiPlayer->Force[0]))); - Attacking = false; - return; - } - pos = unit->tilePos; } else { - pos = this->GoalPos; + CommandMove(aiunit, pos, FlushCommands); } - AiForceAttackSender(this, pos); } }