[*] Improved AI collision detection

[-] Correcting transporting
This commit is contained in:
cybermind 2015-02-16 23:14:37 +05:00
parent f80feaecf7
commit 4dafa76a97
6 changed files with 100 additions and 31 deletions

View file

@ -37,6 +37,7 @@
#include "action/action_resource.h"
#include "ai.h"
#include "animation.h"
#include "interface.h"
#include "iolib.h"
@ -384,6 +385,14 @@ int COrder_Resource::MoveToResource_Terrain(CUnit &unit)
return -1;
case PF_REACHED:
return 1;
case PF_WAIT:
if (unit.Player->AiEnabled) {
this->Range++;
if (this->Range >= 5) {
this->Range = 0;
AiCanNotMove(unit);
}
}
default:
return 0;
}
@ -404,6 +413,14 @@ int COrder_Resource::MoveToResource_Unit(CUnit &unit)
return -1;
case PF_REACHED:
break;
case PF_WAIT:
if (unit.Player->AiEnabled) {
this->Range++;
if (this->Range >= 5) {
this->Range = 0;
AiCanNotMove(unit);
}
}
default:
// Goal gone or something.
if (unit.Anim.Unbreakable || goal->IsVisibleAsGoal(*unit.Player)) {
@ -899,6 +916,14 @@ int COrder_Resource::MoveToDepot(CUnit &unit)
return -1;
case PF_REACHED:
break;
case PF_WAIT:
if (unit.Player->AiEnabled) {
this->Range++;
if (this->Range >= 5) {
this->Range = 0;
AiCanNotMove(unit);
}
}
default:
if (unit.Anim.Unbreakable || goal.IsVisibleAsGoal(player)) {
return 0;
@ -1136,6 +1161,7 @@ bool COrder_Resource::ActionResourceInit(CUnit &unit)
{
Assert(this->State == SUB_START_RESOURCE);
this->Range = 0;
CUnit *const goal = this->GetGoal();
CUnit *mine = this->Resource.Mine;

View file

@ -833,8 +833,8 @@ static void AiMoveUnitInTheWay(CUnit &unit)
AiPlayer = unit.Player->Ai;
// No more than 1 move per 3 cycle ( avoid stressing the pathfinder )
if (GameCycle <= AiPlayer->LastCanNotMoveGameCycle + 3) {
// No more than 1 move per 10 cycle ( avoid stressing the pathfinder )
if (GameCycle <= AiPlayer->LastCanNotMoveGameCycle + 10) {
return;
}
@ -851,7 +851,7 @@ static void AiMoveUnitInTheWay(CUnit &unit)
if (blocker.IsUnusable()) {
continue;
}
if (!blocker.IsIdle()) {
if (!blocker.CanMove() || blocker.Moving) {
continue;
}
if (blocker.Player != unit.Player && blocker.Player->IsAllied(*unit.Player) == false) {
@ -862,9 +862,6 @@ static void AiMoveUnitInTheWay(CUnit &unit)
if (blockertype.UnitType != unittype.UnitType) {
continue;
}
if (!blocker.CanMove()) {
continue;
}
const Vec2i b0 = blocker.tilePos;
const Vec2i b1(b0.x + blockertype.TileWidth - 1, b0.y + blockertype.TileHeight - 1);
@ -884,7 +881,7 @@ static void AiMoveUnitInTheWay(CUnit &unit)
r = (r + 1) & 7;
--trycount;
const Vec2i pos = blocker.tilePos + dirs[r];
const Vec2i pos = blocker.tilePos + blocker.Type->TileWidth * dirs[r];
// Out of the map => no !
if (!Map.Info.IsPointOnMap(pos)) {
@ -894,6 +891,9 @@ static void AiMoveUnitInTheWay(CUnit &unit)
if (pos == u0) {
continue;
}
if (Map.Field(pos)->UnitCache.size() > 0) {
continue;
}
movableunits[movablenb] = &blocker;
movablepos[movablenb] = pos;
@ -909,8 +909,16 @@ static void AiMoveUnitInTheWay(CUnit &unit)
// Don't move more than 1 unit.
if (movablenb) {
const int index = SyncRand() % movablenb;
COrder *savedOrder = NULL;
if (movableunits[index]->IsIdle() == false) {
if (unit.CanStoreOrder(unit.CurrentOrder())) {
savedOrder = unit.CurrentOrder()->Clone();
}
}
CommandMove(*movableunits[index], movablepos[index], FlushCommands);
if (savedOrder != NULL) {
unit.SavedOrder = savedOrder;
}
AiPlayer->LastCanNotMoveGameCycle = GameCycle;
}
}

View file

@ -378,10 +378,22 @@ void AiForce::Attack(const Vec2i &pos)
}
Vec2i goalPos(pos);
bool isNaval = false;
for (size_t i = 0; i != this->Units.size(); ++i) {
CUnit *const unit = this->Units[i];
if (unit->Type->UnitType == UnitTypeNaval && unit->Type->CanAttack) {
isNaval = true;
break;
}
}
if (Map.Info.IsPointOnMap(goalPos) == false) {
/* Search in entire map */
const CUnit *enemy = NULL;
AiForceEnemyFinder<AIATTACK_BUILDING>(*this, &enemy);
if (isNaval) {
AiForceEnemyFinder<AIATTACK_ALLMAP>(*this, &enemy);
} else {
AiForceEnemyFinder<AIATTACK_BUILDING>(*this, &enemy);
}
if (enemy) {
goalPos = enemy->tilePos;
}
@ -571,9 +583,15 @@ void AiForceManager::CheckUnits(int *counter)
}
for (unsigned int j = 0; j < force.UnitTypes.size(); ++j) {
const AiUnitType &aiut = force.UnitTypes[j];
const int t = aiut.Type->Slot;
const unsigned int t = aiut.Type->Slot;
const int wantedCount = aiut.Want;
const int requested = wantedCount - (unit_types_count[t] + counter[t] - attacking[t]);
int e = unit_types_count[t];
if (t < AiHelpers.Equiv.size()) {
for (unsigned int j = 0; j < AiHelpers.Equiv[t].size(); ++j) {
e += unit_types_count[AiHelpers.Equiv[t][j]->Slot];
}
}
const int requested = wantedCount - (e + counter[t] - attacking[t]);
if (requested > 0) { // Request it.
AiAddUnitTypeRequest(*aiut.Type, requested);
@ -778,27 +796,28 @@ static void AiGroupAttackerForTransport(AiForce &aiForce)
CUnit &unit = *aiForce.Units[i];
CUnit &transporter = *aiForce.Units[transporterIndex];
if (transporter.IsIdle()
&& unit.CurrentAction() == UnitActionBoard
if (unit.CurrentAction() == UnitActionBoard
&& static_cast<COrder_Board *>(unit.CurrentOrder())->GetGoal() == &transporter) {
CommandFollow(transporter, unit, 0);
}
if (CanTransport(transporter, unit) && unit.IsIdle() && unit.Container == NULL) {
CommandBoard(unit, transporter, FlushCommands);
CommandFollow(transporter, unit, 0);
if (--nbToTransport == 0) { // full : next transporter.
for (++transporterIndex; transporterIndex < aiForce.Size(); ++transporterIndex) {
const CUnit &nextTransporter = *aiForce.Units[transporterIndex];
if (CanTransport(transporter, unit) && (unit.IsIdle()
|| (unit.CurrentAction() == UnitActionBoard && !unit.Moving
&& static_cast<COrder_Board *>(unit.CurrentOrder())->GetGoal() != &transporter)) && unit.Container == NULL) {
CommandBoard(unit, transporter, FlushCommands);
CommandFollow(transporter, unit, 0);
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;
if (nextTransporter.Type->CanTransport()) {
nbToTransport = nextTransporter.Type->MaxOnBoard - nextTransporter.BoardCount;
break ;
}
}
if (transporterIndex == aiForce.Size()) { // No more transporter.
break ;
}
}
if (transporterIndex == aiForce.Size()) { // No more transporter.
break ;
}
}
}
}
}
@ -964,7 +983,19 @@ void AiForce::Update()
if (State == AiForceAttackingState_Attacking && idleUnits.size() == this->Size()) {
const CUnit *unit = NULL;
AiForceEnemyFinder<AIATTACK_BUILDING>(*this, &unit);
bool isNaval = false;
for (size_t i = 0; i != this->Units.size(); ++i) {
CUnit *const unit = this->Units[i];
if (unit->Type->UnitType == UnitTypeNaval && unit->Type->CanAttack) {
isNaval = true;
break;
}
}
if (isNaval) {
AiForceEnemyFinder<AIATTACK_ALLMAP>(*this, &unit);
} else {
AiForceEnemyFinder<AIATTACK_BUILDING>(*this, &unit);
}
if (!unit) {
// No enemy found, give up
// FIXME: should the force go home or keep trying to attack?

View file

@ -42,7 +42,7 @@ class COrder_Resource : public COrder
public:
COrder_Resource(CUnit &harvester) : COrder(UnitActionResource), worker(&harvester),
CurrentResource(0), State(0), TimeToHarvest(0), DoneHarvesting(false)
CurrentResource(0), State(0), TimeToHarvest(0), DoneHarvesting(false), Range(0)
{
Resource.Pos.x = Resource.Pos.y = -1;
goalPos.x = goalPos.y = -1;
@ -94,6 +94,7 @@ private:
int State;
int TimeToHarvest; /// how much time until we harvest some more.
bool DoneHarvesting; /// Harvesting done, wait for action to break.
int Range;
#if 1
// duplicate of Resource.Pos ?
Vec2i goalPos;

View file

@ -527,7 +527,7 @@ static int CostMoveToCallBack_Default(unsigned int index, const CUnit &unit)
do {
const int flag = mf->Flags & mask;
if (flag && (AStarKnowUnseenTerrain || mf->playerInfo.IsExplored(*unit.Player))) {
if ((unit.Player->AiEnabled == false) && (flag & ~(MapFieldLandUnit | MapFieldAirUnit | MapFieldSeaUnit))) {
if (flag & ~(MapFieldLandUnit | MapFieldAirUnit | MapFieldSeaUnit)) {
// we can't cross fixed units and other unpassable things
return -1;
}

View file

@ -216,10 +216,13 @@ class BestDepotFinder
return;
}
// calck real travel distance
if (!worker->Container) {
d = UnitReachable(*worker, *dest, 1);
if (best_dist == INT_MAX) {
best_depot = dest;
}
// calck real travel distance
d = UnitReachable(worker->Container ? *worker->Container : *worker, *dest, 1);
//
// Take this depot?
//