// Assets/Scripts/Services/BombService.cs using System; using System.Collections.Generic; using System.Linq; using Cysharp.Threading.Tasks; using Enums; using Models; using Services.Interfaces; using UnityEngine; namespace Services { public class BombService : IBombService { public IReadOnlyList CollectTriggeredBombs(IReadOnlyList matchPositions) { if (matchPositions == null || matchPositions.Count == 0) return Array.Empty(); HashSet candidates = new HashSet(); foreach (Vector2Int p in matchPositions) { candidates.Add(p + Vector2Int.left); candidates.Add(p + Vector2Int.right); candidates.Add(p + Vector2Int.up); candidates.Add(p + Vector2Int.down); } return candidates.ToList(); } public async UniTask DetonateChainAsync( IReadOnlyList initialBombs, Func inBounds, Func getGemAt, Func destroyAtAsync, int radius, float bombDelaySeconds, float bombSelfDelaySeconds) { if (initialBombs == null || initialBombs.Count == 0) return; Queue queue = new Queue(initialBombs); HashSet processed = new HashSet(); while (queue.Count > 0) { Vector2Int bombPos = queue.Dequeue(); if (processed.Contains(bombPos)) continue; if (!inBounds(bombPos)) continue; Gem bomb = getGemAt(bombPos); if (bomb is not { Type: GemType.Bomb }) continue; processed.Add(bombPos); int neighborDelayMs = Mathf.Max(0, Mathf.RoundToInt(bombDelaySeconds * 1000f)); if (neighborDelayMs > 0) await UniTask.Delay(neighborDelayMs); foreach (Vector2Int n in DiamondNeighbors(bombPos, radius)) { if (!inBounds(n)) continue; Gem g = getGemAt(n); if (g == null) continue; if (g.Type == GemType.Bomb) { if (!processed.Contains(n)) queue.Enqueue(n); continue; } await destroyAtAsync(n); } int selfDelayMs = Mathf.Max(0, Mathf.RoundToInt(bombSelfDelaySeconds * 1000f)); if (selfDelayMs > 0) await UniTask.Delay(selfDelayMs); Gem stillBomb = getGemAt(bombPos); if (stillBomb is { Type: GemType.Bomb }) await destroyAtAsync(bombPos); } } private static IEnumerable DiamondNeighbors(Vector2Int center, int radius) { for (int x = -radius; x <= radius; x++) { int maxY = radius - Mathf.Abs(x); for (int y = -maxY; y <= maxY; y++) { if (x == 0 && y == 0) continue; yield return new Vector2Int(center.x + x, center.y + y); } } } } }