Skip to content

Commit

Permalink
Add AI logic for Hackers and improve dozer one a bit
Browse files Browse the repository at this point in the history
  • Loading branch information
MustaphaTR committed Jan 15, 2018
1 parent 01282ec commit 6779f97
Showing 1 changed file with 80 additions and 4 deletions.
84 changes: 80 additions & 4 deletions OpenRA.Mods.Common/AI/HackyAI.cs
Original file line number Diff line number Diff line change
Expand Up @@ -52,6 +52,7 @@ public class UnitCategories
public readonly HashSet<string> NavalUnits = new HashSet<string>();
public readonly HashSet<string> Seige = new HashSet<string>();
public readonly HashSet<string> Collector = new HashSet<string>();
public readonly HashSet<string> FragileDeployer = new HashSet<string>();
public readonly HashSet<string> ExcludeFromSquads = new HashSet<string>();
}

Expand Down Expand Up @@ -161,8 +162,11 @@ public class BuildingCategories
[Desc("Radius in cells around a factory scanned for rally points by the AI.")]
public readonly int RallyPointScanRadius = 8;

[Desc("Radius in cells around base center to send dozer after building it.")]
public readonly int DozerSendingRadius = 16;
[Desc("Minimum radius in cells around base center to send dozer after building it.")]
public readonly int MinDozerSendingRadius = 4;

[Desc("Maximum radius in cells around base center to send dozer after building it.")]
public readonly int MaxDozerSendingRadius = 16;

[Desc("Minimum distance in cells from center of the base when checking for building placement.")]
public readonly int MinBaseRadius = 2;
Expand Down Expand Up @@ -631,6 +635,31 @@ bool HasAdequateAirUnitReloadBuildings(ActorInfo actorInfo)
return null;
}

CPos FindPosFrontForUnit(CPos center, CVec front, int minRange, int maxRange, Actor actor)
{
var mobile = actor.TraitOrDefault<Mobile>();
if (mobile == null)
return center;

// zero vector case. we can't define front or rear.
if (front == CVec.Zero)
return FindPosForUnit(center, center, minRange, maxRange, actor);

var cells = Map.FindTilesInAnnulus(center, minRange, maxRange).Shuffle(Random);
foreach (var cell in cells)
{
var v = cell - center;
if (!mobile.CanEnterCell(cell))
continue;

if (CVec.Dot(front, v) > 0)
return cell;
}

// Front is so full of stuff that we can't move there.
return center;
}

// Find the buildable cell that is closest to pos and centered around center
CPos? FindPos(CPos center, CPos target, int minRange, int maxRange,
string actorType, BuildingInfo bi, bool distanceToBaseIsImportant)
Expand All @@ -657,6 +686,32 @@ bool HasAdequateAirUnitReloadBuildings(ActorInfo actorInfo)
return null;
}

// Find the moveable cell that is closest to pos and centered around center
CPos FindPosForUnit(CPos center, CPos target, int minRange, int maxRange, Actor actor)
{
var mobile = actor.TraitOrDefault<Mobile>();
if (mobile == null)
return center;

var cells = Map.FindTilesInAnnulus(center, minRange, maxRange);

// Sort by distance to target if we have one
if (center != target)
cells = cells.OrderBy(c => (c - target).LengthSquared);
else
cells = cells.Shuffle(Random);

foreach (var cell in cells)
{
if (!mobile.CanEnterCell(cell))
continue;

return cell;
}

return center;
}

CPos defenseCenter;
public CPos? ChooseBuildLocation(string actorType, bool distanceToBaseIsImportant, BuildingPlacementType type)
{
Expand Down Expand Up @@ -1023,10 +1078,31 @@ void FindNewUnits(Actor self)

foreach (var a in newUnits)
{
var closestEnemy = World.ActorsHavingTrait<Building>().Where(actor => !actor.Disposed && IsOwnedByEnemy(actor))
.ClosestTo(World.Map.CenterOfCell(defenseCenter));
var baseCenter = GetRandomBaseCenter();
var mobile = a.TraitOrDefault<Mobile>();

CVec direction = CVec.Zero;
if (closestEnemy != null)
direction = baseCenter - closestEnemy.Location;

if (a.Info.HasTraitInfo<HarvesterInfo>())
QueueOrder(new Order("Harvest", a, false));
else if (Info.UnitsCommonNames.Dozer.Contains(a.Info.Name))
QueueOrder(new Order("Move", a, Target.FromCell(World, Map.FindTilesInCircle(GetRandomBaseCenter(), Info.DozerSendingRadius).Random(Random)), true));
else if (Info.UnitsCommonNames.FragileDeployer.Contains(a.Info.Name) && mobile != null)
{
QueueOrder(new Order("Move", a, Target
.FromCell(World, FindPosFrontForUnit(baseCenter, direction, Info.MinFragilePlacementRadius, Info.MaxBaseRadius, a)), true));
QueueOrder(new Order("GrantConditionOnDeploy", a, true));
}
else if (Info.UnitsCommonNames.Dozer.Contains(a.Info.Name) && mobile != null)
{
var dozerTargetPos = Map.FindTilesInAnnulus(baseCenter, Info.MinDozerSendingRadius, Info.MaxDozerSendingRadius)
.Where(c => mobile.CanEnterCell(c) && !resourceTypeIndices.Get(Map.GetTerrainIndex(c))).Random(Random);

BotDebug("AI: {0} has chosen {1} to move its Dozer ({2})".F(a.Owner, dozerTargetPos, a));
QueueOrder(new Order("Move", a, Target.FromCell(World, dozerTargetPos), true));
}
else
unitsHangingAroundTheBase.Add(a);

Expand Down

0 comments on commit 6779f97

Please sign in to comment.