Skip to content

Commit

Permalink
Refactor PathGraph.
Browse files Browse the repository at this point in the history
  • Loading branch information
anvilvapre committed Jul 16, 2021
1 parent 627fd4e commit 86cb07a
Show file tree
Hide file tree
Showing 12 changed files with 426 additions and 320 deletions.
67 changes: 48 additions & 19 deletions OpenRA.Mods.Common/Activities/FindAndDeliverResources.cs
Original file line number Diff line number Diff line change
Expand Up @@ -180,42 +180,71 @@ public override bool Tick(Actor self)

var searchRadiusSquared = searchRadius * searchRadius;

var procPos = procLoc.HasValue ? (WPos?)self.World.Map.CenterOfCell(procLoc.Value) : null;
var map = self.World.Map;
var procPos = procLoc.HasValue ? (WPos?)map.CenterOfCell(procLoc.Value) : null;
var harvPos = self.CenterPosition;

// Find any harvestable resources:
List<CPos> path;
using (var search = PathSearch.Search(self.World, mobile.Locomotor, self, BlockedByActor.Stationary, loc =>
domainIndex.IsPassable(self.Location, loc, mobile.Locomotor) && harv.CanHarvestCell(self, loc) && claimLayer.CanClaimCell(self, loc))
.WithCustomCost(loc =>
Func<CPos, int> customCost;

if (procPos.HasValue && harvInfo.ResourceRefineryDirectionPenalty > 0)
{
customCost = loc =>
{
if ((loc - searchFromLoc).LengthSquared > searchRadiusSquared)
return int.MaxValue;
return PathGraph.CostForInvalidCell;
// Add a cost modifier to harvestable cells to prefer resources that are closer to the refinery.
// Add a cost modifier to harvestable cells to prefer resources
// that are closer to the refinery.
// This reduces the tendancy for harvesters to move in straight lines
if (procPos.HasValue && harvInfo.ResourceRefineryDirectionPenalty > 0 && harv.CanHarvestCell(self, loc))
if (harv.CanHarvestCell(self, loc))
{
var pos = self.World.Map.CenterOfCell(loc);
var pos = map.CenterOfCell(loc);
// Calculate harv-cell-refinery angle (cosine rule)
var a = harvPos - procPos.Value;
var b = pos - procPos.Value;
var c = pos - harvPos;
if (b != WVec.Zero && c != WVec.Zero)
if (b != WVec.Zero)
{
var cosA = (int)(512 * (b.LengthSquared + c.LengthSquared - a.LengthSquared) / b.Length / c.Length);
// Cost modifier varies between 0 and ResourceRefineryDirectionPenalty
return Math.Abs(harvInfo.ResourceRefineryDirectionPenalty / 2) + harvInfo.ResourceRefineryDirectionPenalty * cosA / 2048;
var c = pos - harvPos;
if (c != WVec.Zero)
{
var a = harvPos - procPos.Value;
var cosA = (int)(512 * (b.LengthSquared + c.LengthSquared - a.LengthSquared) / b.Length / c.Length);
// Cost modifier varies between 0 and ResourceRefineryDirectionPenalty
return Math.Abs(harvInfo.ResourceRefineryDirectionPenalty / 2) + harvInfo.ResourceRefineryDirectionPenalty * cosA / 2048;
}
}
}
return 0;
})
.FromPoint(searchFromLoc)
.FromPoint(self.Location))
};
}
else
{
customCost = loc =>
{
if ((loc - searchFromLoc).LengthSquared > searchRadiusSquared)
return PathGraph.CostForInvalidCell;
return 0;
};
}

var query = new PathQuery(
queryType: PathQueryType.ConditionUnidirectional,
world: self.World,
locomotor: mobile.Locomotor,
actor: self,
check: BlockedByActor.Stationary,
isGoal: loc => domainIndex.IsPassable(self.Location, loc, mobile.Locomotor)
&& harv.CanHarvestCell(self, loc)
&& claimLayer.CanClaimCell(self, loc),
customCost: customCost,
fromPositions: self.Location.Equals(searchFromLoc) ?
new CPos[] { self.Location } : new CPos[] { searchFromLoc, self.Location });

using (var search = new PathSearch(query))
path = mobile.Pathfinder.FindPath(search);

if (path.Count > 0)
Expand Down
15 changes: 12 additions & 3 deletions OpenRA.Mods.Common/Activities/Move/Move.cs
Original file line number Diff line number Diff line change
Expand Up @@ -61,10 +61,19 @@ public Move(Actor self, CPos destination, Color? targetLineColor = null)
getPath = check =>
{
List<CPos> path;
using (var search =
PathSearch.FromPoint(self.World, mobile.Locomotor, self, mobile.ToCell, destination, check)
.WithoutLaneBias())
var query = new PathQuery(
queryType: PathQueryType.PositionUnidirectional,
world: self.World,
locomotor: mobile.Locomotor,
actor: self,
laneBiasDisabled: true,
fromPosition: mobile.ToCell,
toPosition: destination,
check: check);
using (var search = new PathSearch(query))
path = mobile.Pathfinder.FindPath(search);
return path;
};

Expand Down
23 changes: 21 additions & 2 deletions OpenRA.Mods.Common/Activities/Move/MoveAdjacentTo.cs
Original file line number Diff line number Diff line change
Expand Up @@ -132,8 +132,27 @@ List<CPos> CalculatePathToTarget(Actor self, BlockedByActor check)
if (!searchCells.Any())
return NoPath;

using (var fromSrc = PathSearch.FromPoints(self.World, Mobile.Locomotor, self, searchCells, loc, check))
using (var fromDest = PathSearch.FromPoint(self.World, Mobile.Locomotor, self, loc, lastVisibleTargetLocation, check).Reverse())
var fromSrcQuery = new PathQuery(
queryType: PathQueryType.PositionBidirectional,
world: self.World,
locomotor: Mobile.Locomotor,
actor: self,
fromPositions: searchCells,
toPosition: loc,
check: check);

var fromDestQuery = new PathQuery(
queryType: PathQueryType.PositionBidirectional,
world: self.World,
locomotor: Mobile.Locomotor,
actor: self,
fromPosition: loc,
toPosition: lastVisibleTargetLocation,
check: check,
reverse: true);

using (var fromSrc = new PathSearch(fromSrcQuery))
using (var fromDest = new PathSearch(fromDestQuery))
return Mobile.Pathfinder.FindBidiPath(fromSrc, fromDest);
}

Expand Down
Loading

0 comments on commit 86cb07a

Please sign in to comment.