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; }
@ -200,72 +180,61 @@ 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]; TArray<AHexTile*> WorkingSegment;
int32 BeforeBend; AHexTile* Start = PCRef->CurrentHex;
int32 AfterBend; WorkingSegment.Add(Start);
int32 HexIter = 1; int32 i = 0;
FHexVector pDir;
FHexVector PrevDir = FHexVector(Path[0], Start);
FHexVector DirA; FHexVector DirA;
FHexVector DirB; int32 HexesBeforeBend = 1;
AHexTile* Current; for (i; i < Len-1; i++) {
WorkingSegment.Add(Path[i]);
while (Milestone != Path[Len - 1]) { DirA = FHexVector(Path[i+1], Path[i]);
// find Milestone (i.e. end of first curve) & determine curve data if (DirA != PrevDir) { break; }
BeforeBend = 1; HexesBeforeBend++;
for (HexIter; HexIter < Len; HexIter++) { PrevDir = DirA;
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;
for (int32 i = Path.Find(Milestone); i < HexIter; i++) { WorkingSegment.Add(Path[i]); }
Milestone = WorkingSegment.Last();
Current = WorkingSegment[0];
bool bFirstDiagTaken = false;
TArray<AHexTile*> NewSegment; // ideally the entire shortcut (ends at bBlock, whence we continue by A*)
// link from Current to Milestone
for (int32 i = 0; i < BeforeBend; i++) {
Current = WorkingSegment[i];
AHexTile* NewCandidate = Grid[GridIndex(Current->Q + Diag.Q, Current->R + Diag.R)];
if (!DiagIsReachable(Current, Diag) || !NewCandidate->bFree) {
if (bFirstDiagTaken) { break; }
NewSegment.Add(Current);
continue;
}
NewSegment.Add(NewCandidate);
bFirstDiagTaken = true;
}
// Check how much remains until we reach milestone and
// Connect the rest recursively via A* (with shortcuts)
// Consider whether the resulting path really is shorter
Shortcut.Append(NewSegment);
} }
PrevDir = DirA;
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; }
// debug
UE_LOG(LogTemp, Warning, TEXT("Before bend: %d"), HexesBeforeBend);
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); }
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);
// Construct shortcut
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)