Implement L and T Shapes
This commit is contained in:
@@ -183,10 +183,10 @@ namespace Services {
|
|||||||
private async UniTask DestroyMatchesAsync(List<Vector2Int> protectedPositions) {
|
private async UniTask DestroyMatchesAsync(List<Vector2Int> protectedPositions) {
|
||||||
List<Vector2Int> matchPositions = new List<Vector2Int>(this.matchService.CurrentMatches.Count);
|
List<Vector2Int> matchPositions = new List<Vector2Int>(this.matchService.CurrentMatches.Count);
|
||||||
for (int i = 0; i < this.matchService.CurrentMatches.Count; i++) {
|
for (int i = 0; i < this.matchService.CurrentMatches.Count; i++) {
|
||||||
var m = this.matchService.CurrentMatches[i];
|
Gem match = this.matchService.CurrentMatches[i];
|
||||||
if (m == null) continue;
|
if (match == null) continue;
|
||||||
|
|
||||||
Vector2Int pos = m.Position;
|
Vector2Int pos = match.Position;
|
||||||
if (protectedPositions != null && protectedPositions.Contains(pos))
|
if (protectedPositions != null && protectedPositions.Contains(pos))
|
||||||
continue;
|
continue;
|
||||||
|
|
||||||
|
|||||||
@@ -88,12 +88,80 @@ namespace Services {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if (this.currentMatches.Count > 0)
|
||||||
|
this.currentMatches = this.currentMatches.Distinct().ToList();
|
||||||
|
|
||||||
|
ExpandMatchesForLTShapes();
|
||||||
|
|
||||||
if (this.currentMatches.Count > 0)
|
if (this.currentMatches.Count > 0)
|
||||||
this.currentMatches = this.currentMatches.Distinct().ToList();
|
this.currentMatches = this.currentMatches.Distinct().ToList();
|
||||||
|
|
||||||
DetectBombSpawnFromLastSwap();
|
DetectBombSpawnFromLastSwap();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
private void ExpandMatchesForLTShapes() {
|
||||||
|
if (this.currentMatches.Count == 0)
|
||||||
|
return;
|
||||||
|
|
||||||
|
List<Gem> seeds = this.currentMatches.ToList();
|
||||||
|
|
||||||
|
foreach (Gem pivotGem in seeds) {
|
||||||
|
if (pivotGem == null)
|
||||||
|
continue;
|
||||||
|
|
||||||
|
Vector2Int pivot = pivotGem.Position;
|
||||||
|
|
||||||
|
int left = CountLine(pivot, Vector2Int.left);
|
||||||
|
int right = CountLine(pivot, Vector2Int.right);
|
||||||
|
int up = CountLine(pivot, Vector2Int.up);
|
||||||
|
int down = CountLine(pivot, Vector2Int.down);
|
||||||
|
|
||||||
|
int horizontalLen = left + 1 + right;
|
||||||
|
int verticalLen = up + 1 + down;
|
||||||
|
|
||||||
|
bool hasHorizontalMatch = horizontalLen >= 3;
|
||||||
|
bool hasVerticalMatch = verticalLen >= 3;
|
||||||
|
|
||||||
|
// one more in the perpendicular direction = length = 2
|
||||||
|
bool hasHorizontalArm = horizontalLen >= 2;
|
||||||
|
bool hasVerticalArm = verticalLen >= 2;
|
||||||
|
|
||||||
|
// Main horizontal + vertical arm = include vertical run
|
||||||
|
if (hasHorizontalMatch && hasVerticalArm) {
|
||||||
|
AddRun(pivot, Vector2Int.up);
|
||||||
|
AddRun(pivot, Vector2Int.down);
|
||||||
|
this.currentMatches.Add(pivotGem);
|
||||||
|
}
|
||||||
|
|
||||||
|
// Main vertical + horizontal arm = include horizontal run
|
||||||
|
if (hasVerticalMatch && hasHorizontalArm) {
|
||||||
|
AddRun(pivot, Vector2Int.left);
|
||||||
|
AddRun(pivot, Vector2Int.right);
|
||||||
|
this.currentMatches.Add(pivotGem);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
private void AddRun(Vector2Int start, Vector2Int direction) {
|
||||||
|
Gem startGem = this.gameBoard.GetGemAt(start);
|
||||||
|
if (startGem == null)
|
||||||
|
return;
|
||||||
|
|
||||||
|
GemType color = startGem.MatchColor;
|
||||||
|
|
||||||
|
Vector2Int position = start + direction;
|
||||||
|
while (position.x >= 0 && position.x < this.gameBoard.Width &&
|
||||||
|
position.y >= 0 && position.y < this.gameBoard.Height) {
|
||||||
|
|
||||||
|
Gem g = this.gameBoard.GetGemAt(position);
|
||||||
|
if (g == null || g.MatchColor != color)
|
||||||
|
break;
|
||||||
|
|
||||||
|
this.currentMatches.Add(g);
|
||||||
|
position += direction;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
private void DetectBombSpawnFromLastSwap() {
|
private void DetectBombSpawnFromLastSwap() {
|
||||||
Vector2Int from = this.lastSwapFrom;
|
Vector2Int from = this.lastSwapFrom;
|
||||||
Vector2Int to = this.lastSwapTo;
|
Vector2Int to = this.lastSwapTo;
|
||||||
@@ -114,20 +182,67 @@ namespace Services {
|
|||||||
if (this.currentMatches.All(g => g.Position != pivot))
|
if (this.currentMatches.All(g => g.Position != pivot))
|
||||||
return;
|
return;
|
||||||
|
|
||||||
int horizontal = CountLine(pivot, Vector2Int.left) + 1 + CountLine(pivot, Vector2Int.right);
|
// NEW RULE:
|
||||||
int vertical = CountLine(pivot, Vector2Int.up) + 1 + CountLine(pivot, Vector2Int.down);
|
// If the match group that includes this pivot (including L/T expansions) has 4+ gems, spawn a bomb.
|
||||||
|
int groupSize = GetMatchedGroupSizeIncludingLT(pivot);
|
||||||
int best = Mathf.Max(horizontal, vertical);
|
if (groupSize < 4)
|
||||||
if (best < 4)
|
|
||||||
return;
|
return;
|
||||||
|
|
||||||
// Spawn a bomb on the creating slot with the same color group.
|
|
||||||
// Prevent duplicates for the same cell.
|
// Prevent duplicates for the same cell.
|
||||||
if (this.pendingBombSpawns.Any(b => b.Position == pivot))
|
if (this.pendingBombSpawns.Any(b => b.Position == pivot))
|
||||||
return;
|
return;
|
||||||
|
|
||||||
this.pendingBombSpawns.Add(new BombSpawnRequest(pivot, pivotGem.MatchColor));
|
this.pendingBombSpawns.Add(new BombSpawnRequest(pivot, pivotGem.MatchColor));
|
||||||
}
|
}
|
||||||
|
|
||||||
|
private int GetMatchedGroupSizeIncludingLT(Vector2Int pivot) {
|
||||||
|
Gem pivotGem = this.gameBoard.GetGemAt(pivot);
|
||||||
|
if (pivotGem == null)
|
||||||
|
return 0;
|
||||||
|
|
||||||
|
GemType color = pivotGem.MatchColor;
|
||||||
|
|
||||||
|
// Only count gems that are actually in currentMatches (which already includes L/T expansions).
|
||||||
|
HashSet<Vector2Int> matchedPositions = new HashSet<Vector2Int>(
|
||||||
|
this.currentMatches
|
||||||
|
.Where(g => g != null && g.MatchColor == color)
|
||||||
|
.Select(g => g.Position)
|
||||||
|
);
|
||||||
|
|
||||||
|
if (!matchedPositions.Contains(pivot))
|
||||||
|
return 0;
|
||||||
|
|
||||||
|
Queue<Vector2Int> queue = new Queue<Vector2Int>();
|
||||||
|
HashSet<Vector2Int> visited = new HashSet<Vector2Int>();
|
||||||
|
|
||||||
|
queue.Enqueue(pivot);
|
||||||
|
visited.Add(pivot);
|
||||||
|
|
||||||
|
Vector2Int[] directions = {
|
||||||
|
Vector2Int.left,
|
||||||
|
Vector2Int.right,
|
||||||
|
Vector2Int.up,
|
||||||
|
Vector2Int.down
|
||||||
|
};
|
||||||
|
|
||||||
|
while (queue.Count > 0) {
|
||||||
|
Vector2Int currentPivot = queue.Dequeue();
|
||||||
|
|
||||||
|
for (int i = 0; i < directions.Length; i++) {
|
||||||
|
Vector2Int n = currentPivot + directions[i];
|
||||||
|
if (visited.Contains(n))
|
||||||
|
continue;
|
||||||
|
|
||||||
|
if (!matchedPositions.Contains(n))
|
||||||
|
continue;
|
||||||
|
|
||||||
|
visited.Add(n);
|
||||||
|
queue.Enqueue(n);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
return visited.Count;
|
||||||
|
}
|
||||||
|
|
||||||
private int CountLine(Vector2Int start, Vector2Int direction) {
|
private int CountLine(Vector2Int start, Vector2Int direction) {
|
||||||
Gem startGem = this.gameBoard.GetGemAt(start);
|
Gem startGem = this.gameBoard.GetGemAt(start);
|
||||||
|
|||||||
Reference in New Issue
Block a user