Skip to content

Commit

Permalink
Units heading in generally opposite directions are now considered blo…
Browse files Browse the repository at this point in the history
…ckers; this fixes pathing deadlocks.
  • Loading branch information
JamesDunne committed Jul 6, 2012
1 parent 9c9a16d commit ba1a36f
Show file tree
Hide file tree
Showing 9 changed files with 47 additions and 28 deletions.
2 changes: 1 addition & 1 deletion OpenRA.Mods.RA/Activities/FindResources.cs
Expand Up @@ -53,7 +53,7 @@ public override Activity Tick(Actor self)

// Find harvestable resources nearby:
var path = self.World.WorldActor.Trait<PathFinder>().FindPath(
PathSearch.Search(self.World, mobileInfo, self.Owner, true)
PathSearch.Search(self.World, mobileInfo, self, true)
.WithCustomCost(loc =>
{
// Avoid enemy territory:
Expand Down
4 changes: 2 additions & 2 deletions OpenRA.Mods.RA/Activities/MoveAdjacentTo.cs
Expand Up @@ -25,7 +25,7 @@ public override Activity Tick( Actor self )

var mobile = self.Trait<Mobile>();

var ps1 = new PathSearch( self.World, mobile.Info, self.Owner )
var ps1 = new PathSearch( self.World, mobile.Info, self )
{
checkForBlocked = true,
heuristic = location => 0,
Expand All @@ -40,7 +40,7 @@ public override Activity Tick( Actor self )

ps1.heuristic = PathSearch.DefaultEstimator( mobile.toCell );

var ps2 = PathSearch.FromPoint( self.World, mobile.Info, self.Owner, mobile.toCell, target.CenterLocation.ToCPos(), true );
var ps2 = PathSearch.FromPoint( self.World, mobile.Info, self, mobile.toCell, target.CenterLocation.ToCPos(), true );
var ret = self.World.WorldActor.Trait<PathFinder>().FindBidiPath( ps1, ps2 );

return Util.SequenceActivities( mobile.MoveTo( () => ret ), this );
Expand Down
2 changes: 1 addition & 1 deletion OpenRA.Mods.RA/Crates/GiveUnitCrateAction.cs
Expand Up @@ -66,7 +66,7 @@ IEnumerable<CPos> GetSuitableCells(CPos near)

for (var i = -1; i < 2; i++)
for (var j = -1; j < 2; j++)
if (mi.CanEnterCell(self.World, self.Owner, near + new CVec(i, j), null, true, true))
if (mi.CanEnterCell(self.World, self, near + new CVec(i, j), null, true, true))
yield return near + new CVec(i, j);
}

Expand Down
4 changes: 2 additions & 2 deletions OpenRA.Mods.RA/Harvester.cs
Expand Up @@ -112,7 +112,7 @@ Actor ClosestProc(Actor self, Actor ignore)
// Start a search from each refinery's delivery location:
var mi = self.Info.Traits.Get<MobileInfo>();
var path = self.World.WorldActor.Trait<PathFinder>().FindPath(
PathSearch.FromPoints(self.World, mi, self.Owner, refs.Values.Select(r => r.Location), self.Location, false)
PathSearch.FromPoints(self.World, mi, self, refs.Values.Select(r => r.Location), self.Location, false)
.WithCustomCost((loc) =>
{
if (!refs.ContainsKey(loc)) return 0;
Expand Down Expand Up @@ -349,7 +349,7 @@ public void ResolveOrder(Actor self, Order order)

// Find any harvestable resources:
var path = self.World.WorldActor.Trait<PathFinder>().FindPath(
PathSearch.Search(self.World, mobileInfo, self.Owner, true)
PathSearch.Search(self.World, mobileInfo, self, true)
.WithHeuristic(loc =>
{
// Get the resource at this location:
Expand Down
26 changes: 22 additions & 4 deletions OpenRA.Mods.RA/Move/Mobile.cs
Expand Up @@ -77,7 +77,25 @@ public int MovementCostForCell(World world, CPos cell)
{SubCell.FullCell, new PVecInt(0,0)},
};

public bool CanEnterCell(World world, Player owner, CPos cell, Actor ignoreActor, bool checkTransientActors, bool blockedByMovers)
static bool IsMovingInMyDirection(Actor self, Actor other)
{
if (!other.IsMoving()) return false;
if (self == null) return true;

var selfMobile = self.TraitOrDefault<Mobile>();
if (selfMobile == null) return false;

var otherMobile = other.TraitOrDefault<Mobile>();
if (otherMobile == null) return false;

// Sign of dot-product indicates (roughly) if vectors are facing in same or opposite directions:
var dp = CVec.Dot((selfMobile.toCell - self.Location), (otherMobile.toCell - other.Location));
if (dp <= 0) return false;

return true;
}

public bool CanEnterCell(World world, Actor self, CPos cell, Actor ignoreActor, bool checkTransientActors, bool blockedByMovers)
{
if (MovementCostForCell(world, cell) == int.MaxValue)
return false;
Expand All @@ -88,7 +106,7 @@ public bool CanEnterCell(World world, Player owner, CPos cell, Actor ignoreActor
var blockingActors = world.ActorMap.GetUnitsAt(cell)
.Where(x => x != ignoreActor)
// Neutral/enemy units are blockers. Allied units that are moving are not blockers.
.Where(x => blockedByMovers || ((owner.Stances[x.Owner] != Stance.Ally) || !x.IsMoving()))
.Where(x => blockedByMovers || ((self.Owner.Stances[x.Owner] != Stance.Ally) || !IsMovingInMyDirection(self, x)))
.ToList();

if (checkTransientActors && blockingActors.Count > 0)
Expand All @@ -98,7 +116,7 @@ public bool CanEnterCell(World world, Player owner, CPos cell, Actor ignoreActor
return false;

if (blockingActors.Any(a => !(a.HasTrait<ICrushable>() &&
a.TraitsImplementing<ICrushable>().Any(b => b.CrushableBy(Crushes, owner)))))
a.TraitsImplementing<ICrushable>().Any(b => b.CrushableBy(Crushes, self.Owner)))))
return false;
}

Expand Down Expand Up @@ -347,7 +365,7 @@ public bool CanEnterCell(CPos p)

public bool CanEnterCell(CPos cell, Actor ignoreActor, bool checkTransientActors)
{
return Info.CanEnterCell(self.World, self.Owner, cell, ignoreActor, checkTransientActors, true);
return Info.CanEnterCell(self.World, self, cell, ignoreActor, checkTransientActors, true);
}

public void EnteringCell(Actor self)
Expand Down
4 changes: 2 additions & 2 deletions OpenRA.Mods.RA/Move/Move.cs
Expand Up @@ -32,7 +32,7 @@ public Move(CPos destination)
{
this.getPath = (self,mobile) =>
self.World.WorldActor.Trait<PathFinder>().FindPath(
PathSearch.FromPoint( self.World, mobile.Info, self.Owner, mobile.toCell, destination, false )
PathSearch.FromPoint( self.World, mobile.Info, self, mobile.toCell, destination, false )
.WithoutLaneBias());
this.destination = destination;
this.nearEnough = 0;
Expand All @@ -49,7 +49,7 @@ public Move(CPos destination, Actor ignoreBuilding)
{
this.getPath = (self,mobile) =>
self.World.WorldActor.Trait<PathFinder>().FindPath(
PathSearch.FromPoint( self.World, mobile.Info, self.Owner, mobile.toCell, destination, false )
PathSearch.FromPoint( self.World, mobile.Info, self, mobile.toCell, destination, false )
.WithIgnoredBuilding( ignoreBuilding ));

this.destination = destination;
Expand Down
10 changes: 5 additions & 5 deletions OpenRA.Mods.RA/Move/PathFinder.cs
Expand Up @@ -55,8 +55,8 @@ public List<CPos> FindUnitPath(CPos from, CPos target, Actor self)
var mi = self.Info.Traits.Get<MobileInfo>();

var pb = FindBidiPath(
PathSearch.FromPoint(world, mi, self.Owner, target, from, true),
PathSearch.FromPoint(world, mi, self.Owner, from, target, true).InReverse()
PathSearch.FromPoint(world, mi, self, target, from, true),
PathSearch.FromPoint(world, mi, self, from, target, true).InReverse()
);

CheckSanePath2(pb, from, target);
Expand All @@ -73,11 +73,11 @@ public List<CPos> FindUnitPathToRange(CPos src, CPos target, int range, Actor se
{
var mi = self.Info.Traits.Get<MobileInfo>();
var tilesInRange = world.FindTilesInCircle(target, range)
.Where(t => mi.CanEnterCell(self.World, self.Owner, t, null, true, true));
.Where(t => mi.CanEnterCell(self.World, self, t, null, true, true));

var path = FindBidiPath(
PathSearch.FromPoints(world, mi, self.Owner, tilesInRange, src, true),
PathSearch.FromPoint(world, mi, self.Owner, src, target, true).InReverse()
PathSearch.FromPoints(world, mi, self, tilesInRange, src, true),
PathSearch.FromPoint(world, mi, self, src, target, true).InReverse()
);

return path;
Expand Down
21 changes: 11 additions & 10 deletions OpenRA.Mods.RA/Move/PathSearch.cs
Expand Up @@ -28,14 +28,15 @@ public class PathSearch : IDisposable
public bool inReverse;

MobileInfo mobileInfo;
Player owner;
Actor self;
public Player owner { get { return self.Owner; } }

public PathSearch(World world, MobileInfo mobileInfo, Player owner)
public PathSearch(World world, MobileInfo mobileInfo, Actor self)
{
this.world = world;
cellInfo = InitCellInfo();
this.mobileInfo = mobileInfo;
this.owner = owner;
this.self = self;
customCost = null;
queue = new PriorityQueue<PathDistance>();
}
Expand Down Expand Up @@ -120,7 +121,7 @@ public CPos Expand(World world)
if (costHere == int.MaxValue)
continue;

if (!mobileInfo.CanEnterCell(world, owner, newHere, ignoreBuilding, checkForBlocked, false))
if (!mobileInfo.CanEnterCell(world, self, newHere, ignoreBuilding, checkForBlocked, false))
continue;

if (customBlock != null && customBlock(newHere))
Expand Down Expand Up @@ -182,18 +183,18 @@ public void AddInitialCell(CPos location)
queue.Add(new PathDistance(heuristic(location), location));
}

public static PathSearch Search(World world, MobileInfo mi, Player owner, bool checkForBlocked)
public static PathSearch Search(World world, MobileInfo mi, Actor self, bool checkForBlocked)
{
var search = new PathSearch(world, mi, owner)
var search = new PathSearch(world, mi, self)
{
checkForBlocked = checkForBlocked
};
return search;
}

public static PathSearch FromPoint(World world, MobileInfo mi, Player owner, CPos from, CPos target, bool checkForBlocked)
public static PathSearch FromPoint(World world, MobileInfo mi, Actor self, CPos from, CPos target, bool checkForBlocked)
{
var search = new PathSearch(world, mi, owner)
var search = new PathSearch(world, mi, self)
{
heuristic = DefaultEstimator(target),
checkForBlocked = checkForBlocked
Expand All @@ -203,9 +204,9 @@ public static PathSearch FromPoint(World world, MobileInfo mi, Player owner, CPo
return search;
}

public static PathSearch FromPoints(World world, MobileInfo mi, Player owner, IEnumerable<CPos> froms, CPos target, bool checkForBlocked)
public static PathSearch FromPoints(World world, MobileInfo mi, Actor self, IEnumerable<CPos> froms, CPos target, bool checkForBlocked)
{
var search = new PathSearch(world, mi, owner)
var search = new PathSearch(world, mi, self)
{
heuristic = DefaultEstimator(target),
checkForBlocked = checkForBlocked
Expand Down
2 changes: 1 addition & 1 deletion OpenRA.Mods.RA/Production.cs
Expand Up @@ -129,7 +129,7 @@ static bool CanUseExit(Actor self, ActorInfo producee, ExitInfo s)
var mobileInfo = producee.Traits.GetOrDefault<MobileInfo>();

return mobileInfo == null ||
mobileInfo.CanEnterCell(self.World, self.Owner, self.Location + s.ExitCellVector, self, true, true);
mobileInfo.CanEnterCell(self.World, self, self.Location + s.ExitCellVector, self, true, true);
}
}
}

0 comments on commit ba1a36f

Please sign in to comment.