예제 #1
0
 public bool CanMakeMove(int x, int y)
 {   
     return x >= 0 && y >= 0 
                   && x <= board.GetLength(0) 
                   && y <= board.GetLength(1) 
                   && (board[x, y] == CellState.Empty || board[x, y] == CellState.S);
 }
예제 #2
0
        public static Board MakeBoard(RulesMatrix topRules, RulesMatrix leftRules, CellState[,] matrix)
        {
            if (topRules == null)
            {
                throw new ArgumentNullException(nameof(topRules));
            }

            if (leftRules == null)
            {
                throw new ArgumentNullException(nameof(leftRules));
            }

            if (topRules.NumberOfRules != matrix.GetLength(0))
            {
                throw new ArgumentException(
                          $"The number of TopRules doesn't match the dimension of the matrix. TopRules: {topRules.NumberOfRules} <> Matrix: {matrix.GetLength(0)}");
            }

            if (leftRules.NumberOfRules != matrix.GetLength(1))
            {
                throw new ArgumentException(
                          $"The number of LeftRules doesn't match the dimension of the matrix. LeftRules: {leftRules.NumberOfRules} <> Matrix: {matrix.GetLength(0)}");
            }

            CellState[, ]? newMatrix = CloneMatrix(matrix);

            return(new Board(topRules, leftRules, newMatrix));
        }
예제 #3
0
 public GameOfLife(CellState[,] current)
 {
     _current = current;
     GridSize = new GridSize()
     {
         X = current.GetLength(0), Y = current.GetLength(1)
     };
 }
예제 #4
0
 /// <summary>
 /// Constructor for Board class, sets every block to empty.
 /// </summary>
 public Board()
 {
     for (int i = 0; i < arr.GetLength(0); i++)
     {
         for (int j = 0; j < arr.GetLength(1); j++)
         {
             arr[i, j] = CellState.Empty;
         }
     }
 }
예제 #5
0
 private void AssertCellMatch(CellState[,] cells)
 {
     for (int i = 0; i < cells.GetLength(0); i++)
     {
         for (int j = 0; j < cells.GetLength(1); j++)
         {
             var expectedCell = cells[i, j];
             AssertExpectedCell(expectedCell);
         }
     }
 }
예제 #6
0
 public CellState GetCell(int X, int Y)
 {
     if (X < 0 || X >= Cells.GetLength(0))
     {
         return(CellState.Initial);
     }
     if (Y < 0 || Y >= Cells.GetLength(1))
     {
         return(CellState.Initial);
     }
     return(Cells[X, Y]);
 }
예제 #7
0
        private static CellState[,] CloneMatrix(CellState[,] oldMatrix)
        {
            CellState[, ]? newMatrix = new CellState[oldMatrix.GetLength(0), oldMatrix.GetLength(1)];
            for (int y = 0; y < oldMatrix.GetLength(1); y++)
            {
                for (int x = 0; x < oldMatrix.GetLength(0); x++)
                {
                    newMatrix[x, y] = oldMatrix[x, y];
                }
            }

            return(newMatrix);
        }
예제 #8
0
        public List <CellPoint> UpdateState()
        {
            var changedState = new List <CellPoint>();

            for (var x = 0; x < _current.GetLength(0); x++)
            {
                for (var y = 0; y < _current.GetLength(1); y++)
                {
                    UpdateSingleState(changedState, x, y);
                }
            }
            return(changedState);
        }
예제 #9
0
        private static CellState[,] StepForestFire(CellState[,] state, int f, int p)
        {
            /* Clone our old state, so we can write to our new state
             * without changing any values in the old state. */
            var newState = (CellState[, ])state.Clone();

            int height = state.GetLength(0);
            int width  = state.GetLength(1);

            for (int i = 1; i < height - 1; i++)
            {
                for (int o = 1; o < width - 1; o++)
                {
                    /*
                     * Check the current cell.
                     *
                     * If it's empty, give it a 1/p chance of becoming a tree.
                     *
                     * If it's a tree, check to see if any neighbors are burning.
                     * If so, set the cell's state to burning, otherwise give it
                     * a 1/f chance of combusting.
                     *
                     * If it's burning, set it to empty.
                     */
                    switch (state[i, o])
                    {
                    case CellState.Empty:
                        if (Random.Next(0, p) == 0)
                        {
                            newState[i, o] = CellState.Tree;
                        }
                        break;

                    case CellState.Tree:
                        if (IsNeighbor(state, i, o, CellState.Burning) ||
                            Random.Next(0, f) == 0)
                        {
                            newState[i, o] = CellState.Burning;
                        }
                        break;

                    case CellState.Burning:
                        newState[i, o] = CellState.Empty;
                        break;
                    }
                }
            }

            return(newState);
        }
예제 #10
0
        public override string ToString()
        {
            var sb = new StringBuilder();

            for (var x = 0; x < labirynt.GetLength(0); x++)
            {
                for (var y = 0; y < labirynt.GetLength(1); y++)
                {
                    sb.Append(labirynt[x, y] == CellState.Empty ? " " : "#");
                }
                sb.AppendLine();
            }

            return(sb.ToString());
        }
예제 #11
0
        public static List <Point> DetermineValidRadialPoints(CellState[,] grid, Point p)
        {
            var radialPoints = new List <Point>();

            //right
            if (p.X < grid.GetLength(0) - 1)
            {
                var x = p.X + 1;
                CheckAndAddTopRadial(radialPoints, x, p.Y);
                radialPoints.Add(new Point {
                    X = x, Y = p.Y
                });
                CheckAndAddBottomRadial(grid, radialPoints, x, p.Y);
            }
            //center
            CheckAndAddTopRadial(radialPoints, p.X, p.Y);
            CheckAndAddBottomRadial(grid, radialPoints, p.X, p.Y);

            ///left
            if (p.X > 0)
            {
                var x = p.X - 1;
                CheckAndAddTopRadial(radialPoints, x, p.Y);
                radialPoints.Add(new Point {
                    X = x, Y = p.Y
                });
                CheckAndAddBottomRadial(grid, radialPoints, x, p.Y);
            }

            return(radialPoints);
        }
예제 #12
0
    private CellState[,] StepWires(CellState[,] state)
    {
        var newState = (CellState[, ])state.Clone();

        int height = state.GetLength(0);
        int width  = state.GetLength(1);

        for (int i = 1; i < height - 1; i++)
        {
            for (int o = 1; o < width - 1; o++)
            {
                switch (state[i, o])
                {
                case CellState.Wire:
                    int count = CountNeighbor(state, i, o, CellState.Head);
                    if (count == 1 || count == 2)
                    {
                        newState[i, o] = CellState.Head;
                    }
                    break;

                case CellState.Head:
                    newState[i, o] = CellState.Tail;
                    break;

                case CellState.Tail:
                    newState[i, o] = CellState.Wire;
                    break;
                }
            }
        }


        sourceDelay--;
        if (sourceDelay < 0)
        {
            for (int i = 0; i < sources.Count; ++i)
            {
                newState[sources[i].y, sources[i].x] = CellState.Head;
            }

            sourceDelay = int.MaxValue;
        }

        return(newState);
    }
예제 #13
0
        public static Cell[,] FromCellStateArray(CellState[,] states)
        {
            if (states is null)
            {
                throw new ArgumentNullException(nameof(states));
            }

            Cell[,] cells = new Cell[states.GetLength(0), states.GetLength(1)];
            for (int i = 0; i < cells.GetLength(0); i++)
            {
                for (int j = 0; j < cells.GetLength(1); j++)
                {
                    cells[i, j] = new Cell(states[i, j]);
                }
            }

            return(cells);
        }
예제 #14
0
 private static void CheckAndAddBottomRadial(CellState[,] grid, List <Point> radialPoints, int x, int y)
 {
     if (y < grid.GetLength(1) - 1)
     {
         radialPoints.Add(new Point {
             X = x, Y = y + 1
         });
     }
 }
예제 #15
0
 public Projection(bool[,] matrix, int centerX, int centerY)
 {
     if (centerX < 0 || centerX >= matrix.GetLength(0))
     {
         throw new ArgumentOutOfRangeException();
     }
     if (centerY < 0 || centerY >= matrix.GetLength(1))
     {
         throw new ArgumentOutOfRangeException();
     }
     this.matrix = new CellState[matrix.GetLength(0), matrix.GetLength(1)];
     for (int i = 0; i < matrix.GetLength(0); i++)
     {
         for (int j = 0; j < matrix.GetLength(1); j++)
         {
             this.matrix[i, j] = matrix[i, j] ? CellState.Fill : CellState.Empty;
         }
     }
     this.matrix[centerX, centerY] = CellState.Center;
 }
예제 #16
0
        private void ComputeGridBefore(TableRow tableRow)
        {
            _gridBefore = tableRow.GetGridLeftOffset();
            var spanC =
                tableRow.Elements <TableCell>()
                .Sum(x => x.GetGridSpan());

            if (spanC + _gridBefore > _cells.GetLength(1))
            {
                _gridBefore = 0;
            }
        }
예제 #17
0
        public static string GridAsString(CellState[,] grid)
        {
            var seeSB = new StringBuilder();

            for (int i = 0; i < grid.GetLength(0); i++)
            {
                for (int j = 0; j < grid.GetLength(1); j++)
                {
                    if (grid[i, j] == CellState.Alive)
                    {
                        seeSB.Append('X');
                    }
                    else
                    {
                        seeSB.Append(' ');
                    }
                }
                seeSB.Append('\n');
            }
            return(seeSB.ToString());
        }
예제 #18
0
파일: Player.cs 프로젝트: hulinsky/GoLWF
        public void Show(Graphics g)
        {
            Brush brush;

            CellState[,] cells = universe.GetCellsState();

            for (int j = 0; j < cells.GetLength(1); j++)
            {
                for (int i = 0; i < cells.GetLength(0); i++)
                {
                    if (cells[i, j] == CellState.Alive)
                    {
                        brush = Brushes.Black;
                    }
                    else
                    {
                        brush = Brushes.White;
                    }
                    g.FillRectangle(brush, i * (velikost + mezera), j * (velikost + mezera), velikost, velikost);
                }
            }
        }
예제 #19
0
 private void ApplyRules()
 {
     for (int i = 0; i < _nextGenMatrix.GetLength(0); i++)
     {
         for (int j = 0; j < _nextGenMatrix.GetLength(1); j++)
         {
             int count = CountAliveCellNeighbors(i, j);
             if (count < 2)
             {
                 _nextGenMatrix[i, j] = CellState.Dead;
             }
             if (count > 3)
             {
                 _nextGenMatrix[i, j] = CellState.Dead;
             }
             if (count == 3)
             {
                 _nextGenMatrix[i, j] = CellState.Alive;
             }
         }
     }
 }
예제 #20
0
 public CellState[,] Next()
 {
     for (int i = 0; i < cells.GetLength(0); i++)
     {
         for (int j = 0; j < cells.GetLength(1); j++)
         {
             List <CellState> neighbors = GetNeighbors(i, j);
             int aliveNeighbors         = 0;
             foreach (var neighbor in neighbors)
             {
                 if (neighbor == CellState.Alive)
                 {
                     aliveNeighbors++;
                 }
             }
             if (cells[i, j] == CellState.Alive)
             {
                 if (aliveNeighbors == 2 || aliveNeighbors == 3)
                 {
                     cells[i, j] = CellState.Alive;
                 }
                 else
                 {
                     cells[i, j] = CellState.Dead;
                 }
             }
             else
             {
                 if (aliveNeighbors == 3)
                 {
                     cells[i, j] = CellState.Alive;
                 }
             }
         }
     }
     generationNumber++;
     return(cells);
 }
예제 #21
0
 public Projection(CellState[,] matrix)
 {
     if (centerX < 0 || centerX >= matrix.GetLength(0))
     {
         throw new ArgumentOutOfRangeException();
     }
     if (centerY < 0 || centerY >= matrix.GetLength(1))
     {
         throw new ArgumentOutOfRangeException();
     }
     this.matrix = matrix;
     for (int i = 0; i < matrix.GetLength(0); i++)
     {
         for (int j = 0; j < matrix.GetLength(1); j++)
         {
             if (matrix[i, j] == CellState.Center)
             {
                 centerX = i;
                 centerY = j;
             }
         }
     }
 }
예제 #22
0
        public CellState this[int col, int row]
        {
            get
            {
                // Determin if col value is required to wrap around
                if (col >= cells.GetLength(0))
                {
                    col = 0;
                }
                else if (col < 0)
                {
                    col = cells.GetLength(0) - 1;
                }

                // Determin if row value is required to wrap around
                if (row >= cells.GetLength(1))
                {
                    row = 0;
                }
                else if (row < 0)
                {
                    row = cells.GetLength(1) - 1;
                }


                return(cells[col, row]);
            }
            set
            {
                // Verify value a valid variable type.
                if (value.GetType() == typeof(CellState))
                {
                    cells[col, row] = value;
                }
            }
        }
예제 #23
0
파일: Game.cs 프로젝트: eo39/Ball-Breaker
        private void ShiftRightGameField()
        {
            for (int y = 0; y < gameField.GetLength(1); y++)
            {
                int cellWithOutBallPosition = GetCellWithOutBallPosition(y);

                if (cellWithOutBallPosition < 0)
                {
                    continue;
                }

                for (int x = FieldWidth - 1; x > 0;)
                {
                    if (gameField[x, y].HasBall)
                    {
                        x--;
                    }
                    else
                    {
                        (gameField[x, y], gameField[cellWithOutBallPosition, y]) = (
                            gameField[cellWithOutBallPosition, y], gameField[x, y]);

                        cellWithOutBallPosition--;
                        if (cellWithOutBallPosition < 0)
                        {
                            x = 0;
                        }
                    }
                }
            }

            if (GetEmptyFirstColumnCount() == 0)
            {
                gamePhase       = GamePhase.WaitingSelectArea;
                CanUndoLastTurn = true;

                CalculateDifferentBallsAroundCell();
                CheckDefeat();
            }
            else
            {
                gamePhase = GamePhase.AddBallToEmptyColumns;
            }
        }
예제 #24
0
        private int CountAliveCellNeighbors(int x, int y)
        {
            int count = 0;

            if (y > 0 && _matrix[x, y - 1] == CellState.Alive)
            {
                count++;
            }
            if (x > 0 && _matrix[x - 1, y] == CellState.Alive)
            {
                count++;
            }
            if (y > 0 && x > 0 && _matrix[x - 1, y - 1] == CellState.Alive)
            {
                count++;
            }
            if (x < (_matrix.GetLength(0) - 1) && _matrix[x + 1, y] == CellState.Alive)
            {
                count++;
            }
            if (y < (_matrix.GetLength(1) - 1) && _matrix[x, y + 1] == CellState.Alive)
            {
                count++;
            }
            if (y < (_matrix.GetLength(1) - 1) && x < (_matrix.GetLength(0) - 1) && _matrix[x + 1, y + 1] == CellState.Alive)
            {
                count++;
            }
            if (y < (_matrix.GetLength(1) - 1) && x > 0 && _matrix[x - 1, y + 1] == CellState.Alive)
            {
                count++;
            }
            if (x < (_matrix.GetLength(0) - 1) && y > 0 && _matrix[x + 1, y - 1] == CellState.Alive)
            {
                count++;
            }
            return(count);
        }
예제 #25
0
        public static IEnumerable <Cell> GetRoute(CellState[,] labyrinth, Cell start, Cell finish)
        {
            if (start.Equals(finish))
            {
                return new[] { finish }
            }
            ;

            var queue = new Queue <Cell>();

            queue.Enqueue(start);
            var track = new Dictionary <Cell, Cell> {
                { start, null }
            };

            while (queue.Count != 0)
            {
                var currentCell = queue.Dequeue();

                foreach (var neighbour in GetAccessNeighbours(currentCell).Where(cell => !track.ContainsKey(cell)))
                {
                    queue.Enqueue(neighbour);
                    track.Add(neighbour, currentCell);
                    if (neighbour.Equals(finish))
                    {
                        return(RouteRestore().Reverse());
                    }
                }
            }

            return(null);

            IEnumerable <Cell> GetAccessNeighbours(Cell cell)
            {
                for (int delta = -1; delta < 7; delta += 2)
                {
                    var currentRow    = cell.Row + (delta < 2 ? delta : 0);
                    var currentColumn = cell.Column + (delta > 2 ? delta - 4 : 0);
                    if (currentRow < 0 || currentColumn < 0 ||
                        currentRow >= labyrinth.GetLength(0) ||
                        currentColumn >= labyrinth.GetLength(1) ||
                        labyrinth[currentRow, currentColumn] == CellState.Wall)
                    {
                        continue;
                    }
                    yield return(new Cell(currentRow, currentColumn));
                }
            }

            IEnumerable <Cell> RouteRestore()
            {
                var currentPoint = finish;

                yield return(currentPoint);

                while (track[currentPoint] != null)
                {
                    yield return(track[currentPoint]);

                    currentPoint = track[currentPoint];
                }
            }
        }
    }
예제 #26
0
 public int GetSize()
 {
     return(board.GetLength(0));
 }
예제 #27
0
        private void NewGame()
        {
            // Clear the Gameboard, set the state of all cells to Empty
            for (int i = 0; i < Gameboard.GetLength(0); i++)
            {
                for (int j = 0; j < Gameboard.GetLength(1); j++)
                {
                    Gameboard[i, j] = CellState.Empty;
                }
            }

            // Set the Symbols on screen to Empty
            string      imagePath = string.Empty;
            BitmapImage newImage  = new BitmapImage(new Uri("ms-appx:///" + imagePath));

            GameboardImage00.Source = null;
            GameboardImage01.Source = null;
            GameboardImage02.Source = null;
            GameboardImage10.Source = null;
            GameboardImage11.Source = null;
            GameboardImage12.Source = null;
            GameboardImage20.Source = null;
            GameboardImage21.Source = null;
            GameboardImage22.Source = null;

            // Set the opacity of all row-of-three lines to 0 (invisible)
            GameboardLine00To02.Opacity = 0;
            GameboardLine10To12.Opacity = 0;
            GameboardLine20To22.Opacity = 0;
            GameboardLine00To20.Opacity = 0;
            GameboardLine01To21.Opacity = 0;
            GameboardLine02To22.Opacity = 0;
            GameboardLine00To22.Opacity = 0;
            GameboardLine02To20.Opacity = 0;

            // Clear the EndGame messages
            EndGameMessageTextBlock.Text = string.Empty;
            StartNewGameHint.Text        = string.Empty;

            // Set the behaviour for the computer
            CurrentAIBehaviour = (AIBehaviourComboBox.SelectedIndex < 0) ? (AIBehaviour)0 : (AIBehaviour)AIBehaviourComboBox.SelectedIndex;

            // Set the player to go first
            CurrentPlayersTurn = (StartingPlayerComboBox.SelectedIndex < 0) ? (Players)0 : (Players)StartingPlayerComboBox.SelectedIndex;

            // Set the symbols for each player
            if (SelectPlayerSymbolComboBox.SelectedIndex == 0)
            {
                PlayerSymbol   = CellState.X;
                ComputerSymbol = CellState.O;
            }
            else
            {
                PlayerSymbol   = CellState.O;
                ComputerSymbol = CellState.X;
            }

            // If the user has selected for the computer to go first
            if (CurrentPlayersTurn == Players.Computer)
            {
                DoComputerTurn();
            }
            else
            {
                // wait on the user to make the first move; GameboardButton_Click(), event
            }

            Debug.WriteLine(string.Format("TicTacToe: Starting a new game with setting;"));
            Debug.WriteLine(string.Format("TicTacToe: PlayerSymbol = {0}, ComputerSymbol = {1}, AIBehaviour = {2}, First turn = {3}", PlayerSymbol, ComputerSymbol, CurrentAIBehaviour, CurrentPlayersTurn));
        }
예제 #28
0
 public GameStatus(CellState[,] board)
 {
     BoardWidth  = board.GetLength(1);
     BoardHeight = board.GetLength(0);
 }
예제 #29
0
    private CellState[,] StepForestFire(CellState[,] state, int f, int p)
    {
        /* Clone our old state, so we can write to our new state
         * without changing any values in the old state. */
        var newState = (CellState[, ])state.Clone();

        int height = state.GetLength(0);
        int width  = state.GetLength(1);

        bool playtick  = false;
        bool playwrong = false;

        for (int i = 1; i < height - 1; i++)
        {
            for (int o = 1; o < width - 1; o++)
            {
                /*
                 * Check the current cell.
                 *
                 * If it's empty, give it a 1/p chance of becoming a tree.
                 *
                 * If it's a tree, check to see if any neighbors are burning.
                 * If so, set the cell's state to burning, otherwise give it
                 * a 1/f chance of combusting.
                 *
                 * If it's burning, set it to empty.
                 */
                switch (state[i, o])
                {
                case CellState.Empty:
                    if (Random.Range(0, p) == 0)
                    {
                        newState[i, o] = CellState.Tree;
                        playwrong      = true;
                    }

                    if (IsNeighbor(state, i, o, CellState.Tree) && Random.Range(0, nearbyTreeChance) == 0)
                    {
                        newState[i, o] = CellState.Tree;
                        playwrong      = true;
                    }
                    break;

                case CellState.Tree:
                    if (IsNeighbor(state, i, o, CellState.Burning) ||
                        Random.Range(0, f) == 0)
                    {
                        newState[i, o] = CellState.Burning;
                        playtick       = true;
                    }
                    break;

                case CellState.Burning:
                    newState[i, o] = CellState.Empty;
                    break;
                }
            }
        }

        if (playtick)
        {
            SHGUI.current.PlaySound(SHGUIsound.tick);
        }
        else if (playwrong)
        {
            SHGUI.current.PlaySound(SHGUIsound.wrong);
        }


        return(newState);
    }
예제 #30
0
    protected void TestVisibility()
    {
        // Raycast to walls
        Vector3 startDir = Quaternion.AngleAxis(-0.5f * FOV, Vector3.forward) * FacingDirection;
        Vector3 endDir   = Quaternion.AngleAxis(0.5f * FOV, Vector3.forward) * FacingDirection;

        for (int i = 0; i < FOV_STEPS; ++i)
        {
            Vector3 direction = Vector3.Lerp(startDir, endDir, (float)i * (1.0f / FOV_STEPS)).normalized;
            Ray     ray       = new Ray(transform.position, direction);

#if NPC_DEBUG && DEBUG_FOV_RAYCASTS
            lineRenderer.SetVertexCount(i * 3 + 3);
            lineRenderer.SetPosition(i * 3 + 0, transform.position);
            lineRenderer.SetPosition(i * 3 + 1, transform.position + direction * 1000.0f);
            lineRenderer.SetPosition(i * 3 + 2, transform.position);
#endif

            int width  = cellStates.GetLength(0);
            int height = cellStates.GetLength(1);

            RaycastHit hitInfo;
            if (Physics.Raycast(ray, out hitInfo, 1000.0f, levelLayer))
            {
                if (LevelGen.CellGrid.IsInGrid(hitInfo.point))
                {
                    Vector3 hitCellWorld = hitInfo.point - hitInfo.normal * 0.5f;

                    Point hitCell = LevelGen.CellGrid.GetIdxFromPos(hitCellWorld);

                    if (hitCell.x < 0 || hitCell.y < 0 ||
                        hitCell.x >= width || hitCell.y >= height)
                    {
                        continue;
                    }

                    int hitX = hitCell.x;
                    int hitY = hitCell.y;

                    cellStates[hitX, hitY] = CellState.BLOCKED;
                    pathFindingGrid[hitX, hitY].Accessible = false;

                    // Cast a ray in that direction through the grid from curX,curY to hitX,hitY
                    // and mark the cells we pass through as clear
                    Vector2 startPos = new Vector2(transform.position.x, transform.position.y);

                    Vector2 curPos = startPos;

                    Vector2 direction2D    = new Vector2(direction.x, direction.y);
                    Vector2 invDirection2D = new Vector2(1.0f / direction.x, 1.0f / direction.y);

                    float rayDirX = 5.0f * Mathf.Sign(direction2D.x);
                    float rayDirY = 5.0f * Mathf.Sign(direction2D.y);

                    Vector2 rayDir = new Vector2(rayDirX, rayDirY);

                    int steps = (int)Mathf.Ceil(hitInfo.distance);

                    for (int j = 0; j <= steps; ++j)
                    {
                        // TODO: fudged numbers
                        // Make this more mathematically precise
                        Vector3 pos = curPos + direction2D * ((float)j - 0.5f);

                        Point posCell = LevelGen.CellGrid.GetIdxFromPos(pos);

                        if (posCell.x >= 0 && posCell.y >= 0 &&
                            posCell.x < width && posCell.y < height)
                        {
                            int posX = posCell.x;
                            int posY = posCell.y;

                            if (posX != hitX && posY != hitY)
                            {
                                cellStates[posX, posY] = CellState.CLEAR;
                                pathFindingGrid[posX, posY].Accessible = true;
                            }
                        }
                    }
                }
            }
        }
    }