comprime este codigo al maximo para que pueda usarlo en chatgpt luego como memoria de la IA: “using System;
using System.Collections.Generic;
using UnityEngine;
using System.Linq;
using DG.Tweening;
using Random = System.Random;


public class GemsManager : MonoBehaviour
{
    public Sprite[] sprites;
    public GameObject gemPrefab;
    public GameObject targetPosition;
    public GameObject particleSystemGems;

    private static readonly char[] G = {'R', 'G', 'B', 'Y', 'P'};
    private const int N = 6;
    private static readonly Random Random1 = new(DateTime.Now.Millisecond);
    private static List<List<char>> _board;
    int[,] board = new int[N, N];
    HashSet<Position> positions = new HashSet<Position>();


    class Position
    {
        public int col;
        public int row;
        public float x;
        public float y;
    }

    // Start is called before the first frame update
    private void Start()
    {
        _board = GenerateBoard();

        FillBoard();
        ShowBoard(board); // Debug.Log of the board

        //Debug Log formatted of the _board and in order to see the board
        var mensaje = string.Join("\n", _board.Select(row => string.Join(" ", row)));
        Debug.Log(mensaje);
        GenerateScreenBoard();
        var gems = FindHorizontalLine(board);
        gems.AddRange(FindVerticalLines(board));
        //delay 1 segundo
        if (gems.Count > 0)
        {
            gems = gems.OrderBy(x => x.Item1).ThenBy(x => x.Item2).ToList();
            ShowGems(gems);
            RemoveGems(board, gems);
            ShowBoard(board);
        }
    }

    private void FillBoard()
    {
        for (int i = 0; i < N; i++)
        for (int j = 0; j < N; j++)
            board[i, j] = Array.IndexOf(G, _board[i][j]);
    }

    private void RemoveGems(int[,] board, List<(int, int)> gems)
    {
        foreach (var (x, y) in gems)
        {
            board[x, y] = -1;
            GameObject gem = GameObject.Find($"Piece_{x}_{y}");
            ParticleSystem particleSystem1 = Instantiate(particleSystemGems).GetComponent<ParticleSystem>();
            // Posicionar el sistema de partículas en la posición de la gema, menos la z
            Transform transform1;
            (transform1 = particleSystem1.transform).SetParent(gem.transform);
            transform1.localPosition = new Vector3(1, 1, -1);
            // Activar el sistema de partículas
            // Mover la gema a la posición del objetivo delay 1 segundo
            gem.transform.DOMove(targetPosition.transform.position, 3f).SetDelay(2f)
                .OnStart(() => particleSystem1.Play()).OnComplete(() => Destroy(gem));
        }

        // Hacer que las gemas caigan hacia abajo
        var listaPrimerBlanco = new List<(int, int)>();
        var listaGemas = new List<(int, int)>();
        for (int col = 0; col < N; col++)
        {
            // extraer las gemas no vacías en la columna actual
            var nonEmptyGems = new List<int>();
            for (int row = 0; row < board.GetLength(0); row++)
            {
                if (board[row, col] != -1)
                {
                    nonEmptyGems.Add(board[row, col]);
                }
            }

            var primerFlag = false;
            for (int row = board.GetLength(0) - 1; row >= 0; row--)
            {
                if (board[row, col] != -1)
                {
                    if (primerFlag)
                    {
                        listaGemas.Add((row, col));
                    }
                }
                else
                {
                    primerFlag = true;
                }
            }

            if (nonEmptyGems.Count == 6) continue;
            // agregar valores nulos al principio de la lista nonEmptyGems para que tenga N elementos
            nonEmptyGems.InsertRange(0, Enumerable.Repeat(-1, board.GetLength(0) - nonEmptyGems.Count));

            // reemplazar las gemas en la columna actual con la lista nonEmptyGems actualizada
            // Assign the values from the nonEmptyGems list to the board array, column by column.
            var flag = false;
            for (int row = board.GetLength(0) - 1; row >= 0; row--)
            {
                if (!flag && board[row, col] == -1)
                {
                    flag = true;
                    listaPrimerBlanco.Add((row, col));
                }

                board[row, col] = nonEmptyGems[row];
            }
        }

        // Animar las gemas que caen
        AnimarGemasCaen(listaGemas, listaPrimerBlanco);

        // Generar nuevas gemas aleatorias para llenar los espacios vacíos
        for (int col = 0; col < board.GetLength(1); col++)
        {
            var emptySpaces = new List<int>();
            for (int i = 0; i < board.GetLength(0); i++)
            {
                if (board[i, col] == -1) emptySpaces.Add(i);
            }

            foreach (var i in emptySpaces)
            {
                board[i, col] = Random1.Next(0, G.Length);
                var newPiece = CreateIconsAtPosition(i, col);

                var position = newPiece.transform.position;
                var positionY = position.y - 6f;

                newPiece.transform.DOMoveY(positionY, 1f).SetEase(Ease.Flash)
                    .SetDelay(4f - i/2f);
            }
        }
    }

    private void AnimarGemasCaen(List<(int, int)> listaGemas, List<(int, int)> listaPrimerBlanco)
    {
        foreach (var columnas in listaPrimerBlanco)
        {
            //seleccionar las gemas de la columna en listaPrimerBlanco
            var gemas = listaGemas.Where(x => x.Item2 == columnas.Item2).ToList();
            var target = positions.FirstOrDefault(p => p.row == columnas.Item1 && p.col == columnas.Item2);
            int i = 0;
            foreach (var gema in gemas)
            {
                GameObject gem = GameObject.Find($"Piece_{gema.Item1}_{gema.Item2}");
                gem.transform.DOMoveY(target.y, 1f).SetEase(Ease.InFlash).SetDelay(2f + (i/2f));
                gem.name = $"Piece_{columnas.Item1 - i}_{columnas.Item2}";
                i++;
                if (columnas.Item1 - i >= 0)
                {
                    target = positions.FirstOrDefault(p => p.row == columnas.Item1 - i && p.col == columnas.Item2);
                }
            }
        }
    }

    private void ShowBoard(int[,] board)
    {
        //Debug Log formatted of the board and in order to see the board
        var mensaje = string.Join("\n", board.Cast<int>().Select((value, index) => new {value, index})
            .GroupBy(x => x.index / N)
            .Select(x => string.Join(" ", x.Select(v => v.value))));

        Debug.Log(mensaje);
    }

    private void ShowGems(List<(int, int)> gems)
    {
        // Debug.Log of the List<(int, int)> gems
        var mensaje = string.Join("\n", gems.Select(row => string.Join(" ", row)));
        Debug.Log(mensaje);
    }

    private void GenerateScreenBoard()
    {
        Vector2 screenSize = new Vector2(Screen.width, Screen.height);
        Debug.Log(screenSize);

        float iconSize = 50f;
        float spacing = 15f;

        float tableWidth = 6 * (iconSize + spacing) - spacing;
        float tableHeight = 6 * (iconSize + spacing) - spacing;
        Vector2 tablePosition = (screenSize - new Vector2(tableWidth, tableHeight)) / 2f;

        List<Vector2> iconPositions = CalculateIconPositions(tablePosition, iconSize, spacing);
        List<Vector2> iconWorldPositions = CalculateIconWorldPositions(iconPositions);

        CreateIcons(iconWorldPositions);
    }

    private List<Vector2> CalculateIconPositions(Vector2 tablePosition, float iconSize, float spacing)
    {
        List<Vector2> iconPositions = new List<Vector2>();
        for (int row = 0; row < 6; row++)
        {
            for (int col = 0; col < 6; col++)
            {
                float x = tablePosition.x + col * (iconSize + spacing);
                float y = tablePosition.y + row * (iconSize + spacing);
                iconPositions.Add(new Vector2(x, y));
            }
        }

        return iconPositions;
    }

    private List<Vector2> CalculateIconWorldPositions(List<Vector2> iconPositions)
    {
        List<Vector2> iconWorldPositions = new List<Vector2>();
        foreach (var iconPosition in iconPositions)
        {
            Vector2 iconWorldPosition = Camera.main.ScreenToWorldPoint(new Vector3(iconPosition.x, iconPosition.y, 0));
            iconWorldPositions.Add(iconWorldPosition);
        }

        return iconWorldPositions;
    }

    private void CreateIcons(List<Vector2> iconWorldPositions)
    {
        //create icons with board data
        for (int row = 0; row < 6; row++)
        {
            for (int col = 0; col < 6; col++)
            {
                var rowi = 5 - row;
                int index = rowi * 6 + col;
                Vector2 iconWorldPosition = iconWorldPositions[index];
                char icon = _board[row][col];
                int spriteIndex = Array.IndexOf(G, icon);
                GameObject newPiece = Instantiate(gemPrefab, iconWorldPosition, Quaternion.identity);
                newPiece.transform.parent = transform;
                newPiece.name = $"Piece_{row}_{col}";
                Position pos = new Position();
                pos.row = row;
                pos.col = col;
                pos.x = iconWorldPosition.x;
                pos.y = iconWorldPosition.y;
                positions.Add(pos);
                newPiece.GetComponent<SpriteRenderer>().sprite = sprites[spriteIndex];
            }
        }
    }

    private GameObject CreateIconsAtPosition(int fila, int columna)
    {
        GameObject newPiece = null;
        // Luego, buscamos la posición del mundo correspondiente en la lista ‘positions’
        Position targetPos = null;
        targetPos = positions.FirstOrDefault(p => p.row == fila && p.col == columna);

        if (targetPos != null)
        {
            int spriteIndex = board[fila, columna];
            newPiece = Instantiate(gemPrefab, new Vector2(targetPos.x, targetPos.y + 6f), Quaternion.identity);
            newPiece.transform.parent = transform;
            newPiece.name = $"Piece_{fila}_{columna}";
            newPiece.GetComponent<SpriteRenderer>().sprite = sprites[spriteIndex];
        }

        return newPiece;
    }


    private static List<List<char>> GenerateBoard()
    {
        List<List<char>> board = new List<List<char>>();
        for (int i = 0; i < N; i++)
        {
            List<char> row = new List<char>();
            for (int j = 0; j < N; j++)
            {
                row.Add(G[Random1.Next(0, G.Length)]);
            }

            board.Add(row);
        }

        return board;
    }

    // Update is called once per frame
    private void Update()
    {
    }

"