public void StopIndicatingSwap(Vector2Int gridPos)
        {
            Tile         tile         = board[gridPos];
            TileRenderer tileRenderer = tileDictionary[tile.ID];

            tileRenderer.StopIndicatingSwap();
        }
        private async Task AnimateNewAndFallingTilesAsync(List <MovedTile> newTiles, List <MovedTile> movedTiles)
        {
            Sequence seq = DOTween.Sequence();

            foreach (MovedTile movedTile in newTiles)
            {
                TileRenderer tileRenderer = Instantiate(tileRendererPrefab, transform);

                tileRenderer.SetTile(movedTile.Tile, movedTile.From);
                tileDictionary[movedTile.Tile.ID] = tileRenderer;

                seq.Insert(0, tileRenderer.FallToCurrentPosition(movedTile.From));
            }

            foreach (MovedTile movedTile in movedTiles)
            {
                Tile         tile         = movedTile.Tile;
                TileRenderer tileRenderer = tileDictionary[tile.ID];

                seq.Insert(0, tileRenderer.FallToCurrentPosition(movedTile.From));
            }

            await seq.Completion();

            await new WaitForSeconds(postFallDelay);
        }
        public void IndicateStartOfSwap(Vector2Int gridPos)
        {
            Tile         tile         = board[gridPos];
            TileRenderer tileRenderer = tileDictionary[tile.ID];

            tileRenderer.IndicateStartOfSwap();
        }
        private async Task AnimateInertTilesAsync(HashSet <Tile> inertTiles)
        {
            Sequence seq = DOTween.Sequence();

            foreach (Tile tile in inertTiles)
            {
                TileRenderer tileRenderer = tileDictionary[tile.ID];

                seq.Insert(0, tileRenderer.TransitionToInert());
            }

            await seq.Completion();

            await new WaitForSeconds(postInertDelay);
        }
        private async Task AnimateRotatingTilesAsync(List <MovedTile> movedTiles, Vector2 pivot, RotationSense rotSense)
        {
            Sequence seq = DOTween.Sequence();

            foreach (MovedTile movedTile in movedTiles)
            {
                Tile         tile         = movedTile.Tile;
                TileRenderer tileRenderer = tileDictionary[tile.ID];

                seq.Insert(0, tileRenderer.RotateToCurrentPosition(movedTile.From, pivot, rotSense));
            }

            await seq.Completion();

            await new WaitForSeconds(postFallDelay);
        }
        private async Task AnimateRemovedTilesAsync(HashSet <Tile> removedTiles)
        {
            Sequence seq = DOTween.Sequence();

            foreach (Tile tile in removedTiles)
            {
                TileRenderer tileRenderer = tileDictionary[tile.ID];

                seq.Insert(0, tileRenderer.Destroy());

                tileDictionary.Remove(tile.ID);
            }

            await seq.Completion();

            await new WaitForSeconds(postMatchDelay);
        }
        private async Task AnimateCrackedTilesAsync(HashSet <Tile> crackedTiles)
        {
            Sequence seq = DOTween.Sequence();

            float delay = 0f;

            foreach (Tile tile in crackedTiles)
            {
                if (tile.Cracks == 1)
                {
                    continue;
                }

                TileRenderer tileRenderer = tileDictionary[tile.ID];

                seq.Insert(delay, tileRenderer.UpdateCracks());

                delay += spikeBallDelay;
            }

            foreach (Tile tile in crackedTiles)
            {
                if (tile.Cracks > 1)
                {
                    continue;
                }

                TileRenderer tileRenderer = tileDictionary[tile.ID];

                Vector3 referenceScale = reference11.position - reference00.position;
                Vector3 targetPos      = reference00.position + new Vector3(tile.Position.x * referenceScale.x, tile.Position.y * referenceScale.y);

                Tween spikeBallTween = chainCounter.SendSpikeBall(targetPos);
                seq.Insert(delay, spikeBallTween);

                seq.Insert(delay + spikeBallTween.Duration() - anticipateSpikeBallDestructionBy, tileRenderer.UpdateCracks());

                delay += spikeBallDelay;
            }

            await seq.Completion();

            await new WaitForSeconds(postInertDelay);
        }
        public void RenderInitial(Board board)
        {
            if (cancelAnimation)
            {
                return;
            }

            foreach (TileRenderer tileRenderer in tileDictionary.Values)
            {
                if (tileRenderer)
                {
                    Destroy(tileRenderer.gameObject);
                }
            }

            tileDictionary.Clear();

            this.board = board;

            width  = board.Width;
            height = board.Height;

            for (int x = 0; x < width; ++x)
            {
                for (int y = 0; y < height; ++y)
                {
                    Tile tile = board[x, y];
                    if (tile is null)
                    {
                        continue;
                    }

                    TileRenderer tileRenderer = Instantiate(tileRendererPrefab, transform);

                    tileRenderer.SetTile(tile);
                    tileDictionary[tile.ID] = tileRenderer;
                }
            }
        }