prepared Shortcut rework for A* (working segment data)

This commit is contained in:
Maximilian Fajnberg 2022-02-05 14:26:46 +01:00
parent 1573598c2a
commit 1485621698
3 changed files with 47 additions and 75 deletions

View File

@ -170,26 +170,6 @@ TArray<AHexTile*> AAdventureMap::FindPathAStar(AHexTile* Start, AHexTile* Goal,
ToExamine.Add(Neighbor); ToExamine.Add(Neighbor);
} } } }
} }
/*
if (bDiags) {
for (AHexTile* Diag : FreeDiagonals(Candidate)) {
if (!Diag->bFree) { continue; }
if (Processed.Contains(Diag)) { continue; }
bool bInToExamine = ToExamine.Contains(Diag);
float NewGCost = Candidate->GCost + Diag->MoveCost;
if (NewGCost < Diag->GCost || !bInToExamine) {
Diag->GCost = NewGCost;
Diag->CameFrom = Candidate; // chain
Diag->bDiagMove = true;
if (!bInToExamine) {
Diag->HCost = Diag->Distance(Goal);
ToExamine.Add(Diag);
} }
}
}*/
} }
TArray<AHexTile*> Path; TArray<AHexTile*> Path;
if (!IsValid(Goal->CameFrom)) { return Path; } if (!IsValid(Goal->CameFrom)) { return Path; }
@ -201,71 +181,60 @@ TArray<AHexTile*> AAdventureMap::FindPathAStar(AHexTile* Start, AHexTile* Goal,
Algo::Reverse(Path); Algo::Reverse(Path);
if (bDiags) { if (bDiags) {
Path = ShortcutAStar(Path); TArray<AHexTile*> PathS = ShortcutAStar(Path);
} }
return Path; return Path;
} }
TArray<AHexTile*> AAdventureMap::ShortcutAStar(TArray<AHexTile*> Path) TArray<AHexTile*> AAdventureMap::ShortcutAStar(TArray<AHexTile*> Path)
{ {
TArray<AHexTile*> Shortcut; TArray<AHexTile*> Shortcut;
int32 Len = Path.Num(); int32 Len = Path.Num();
AHexTile* Milestone = Path[0];
int32 BeforeBend;
int32 AfterBend;
int32 HexIter = 1;
FHexVector pDir;
FHexVector DirA;
FHexVector DirB;
AHexTile* Current;
while (Milestone != Path[Len - 1]) {
// find Milestone (i.e. end of first curve) & determine curve data
BeforeBend = 1;
for (HexIter; HexIter < Len; HexIter++) {
pDir = FHexVector(Path[HexIter], Path[HexIter - 1]);
DirA = FHexVector(Path[HexIter + 1], Path[HexIter]);
if (DirA == pDir) { BeforeBend++; }
else { break; }
}
AfterBend = 1;
for (HexIter; HexIter < Len; HexIter++) {
pDir = FHexVector(Path[HexIter], Path[HexIter - 1]);
DirB = FHexVector(Path[HexIter + 1], Path[HexIter]);
if (DirB == pDir) { AfterBend++; }
else { break; }
}
FHexVector Diag = UnitDiagFromUnitNB(DirA, DirB); // (exact diagonal) cardinal direction for shortcut
TArray<AHexTile*> WorkingSegment; TArray<AHexTile*> WorkingSegment;
for (int32 i = Path.Find(Milestone); i < HexIter; i++) { WorkingSegment.Add(Path[i]); } AHexTile* Start = PCRef->CurrentHex;
Milestone = WorkingSegment.Last(); WorkingSegment.Add(Start);
Current = WorkingSegment[0]; int32 i = 0;
bool bFirstDiagTaken = false;
TArray<AHexTile*> NewSegment; // ideally the entire shortcut (ends at bBlock, whence we continue by A*)
// link from Current to Milestone FHexVector PrevDir = FHexVector(Path[0], Start);
for (int32 i = 0; i < BeforeBend; i++) { FHexVector DirA;
Current = WorkingSegment[i]; int32 HexesBeforeBend = 1;
AHexTile* NewCandidate = Grid[GridIndex(Current->Q + Diag.Q, Current->R + Diag.R)]; for (i; i < Len-1; i++) {
if (!DiagIsReachable(Current, Diag) || !NewCandidate->bFree) { WorkingSegment.Add(Path[i]);
if (bFirstDiagTaken) { break; } DirA = FHexVector(Path[i+1], Path[i]);
NewSegment.Add(Current); if (DirA != PrevDir) { break; }
continue; HexesBeforeBend++;
PrevDir = DirA;
} }
NewSegment.Add(NewCandidate); PrevDir = DirA;
bFirstDiagTaken = true; FHexVector DirB;
int32 HexesAfterBend = 0;
for (i; i < Len - 1; i++) {
WorkingSegment.Add(Path[i+1]);
DirB = FHexVector(Path[i+1], Path[i]);
if (DirB != PrevDir) { break; }
HexesAfterBend++;
PrevDir = DirB;
} }
if (HexesAfterBend == 0) { return Path; }
// Check how much remains until we reach milestone and // debug
// Connect the rest recursively via A* (with shortcuts) UE_LOG(LogTemp, Warning, TEXT("Before bend: %d"), HexesBeforeBend);
// Consider whether the resulting path really is shorter UE_LOG(LogTemp, Warning, TEXT("After bend: %d"), HexesAfterBend);
UE_LOG(LogTemp, Warning, TEXT("Working segment length: %d"), WorkingSegment.Num());
for (AHexTile* HexDebug : WorkingSegment) { UE_LOG(LogTemp, Warning, TEXT("HexID: %d"), HexDebug->Index); }
Shortcut.Append(NewSegment);
}
// Construct shortcut FHexVector UnitDiag = UnitDiagFromUnitNB(DirA, DirB);
AHexTile* Milestone = WorkingSegment.Last();
// Try adding diagonal Hexes to Shortcut from Start until Milestone (if BeforeBend>=AferBend: do this AfterBend times, else: BeforeBend)
// Set a bool to 'true' as soon as the first Hex is added; Set CurrentHex to that;
// if the path is blocked and the bool is 'false': Set CurrentHex to the next in WorkingSegment; Retry.
// if the path is blocked and the bool is 'true': Append the rest recursively calling A*(Shortcut.Last(), Path.Last(), true);
// when iterated AfterBend (or BeforeBend) times: Append the rest recursively calling A*(Shortcut.Last(), Path.Last(), true);
return Shortcut; return Shortcut;
} }

View File

@ -30,6 +30,9 @@ public:
UPROPERTY(EditDefaultsOnly, BlueprintReadOnly, Category = "Config") UPROPERTY(EditDefaultsOnly, BlueprintReadOnly, Category = "Config")
int32 TileSize = 100; int32 TileSize = 100;
UPROPERTY(VisibleAnywhere, BlueprintReadWrite)
AAdventurePlayerController* PCRef;
UFUNCTION(BlueprintCallable, Category = "Generation") UFUNCTION(BlueprintCallable, Category = "Generation")
void MakeGrid(); void MakeGrid();
UPROPERTY(BlueprintReadOnly, Category = "Generation") UPROPERTY(BlueprintReadOnly, Category = "Generation")

View File

@ -58,7 +58,7 @@ public:
UPROPERTY() UPROPERTY()
float GCost; float GCost;
UPROPERTY() UPROPERTY()
float HCost; float HCost = 9999;
// MapObject Placement // MapObject Placement
UPROPERTY(BlueprintReadWrite, VisibleAnywhere) UPROPERTY(BlueprintReadWrite, VisibleAnywhere)