예제 #1
0
        public IOrderedEnumerable <Move> GetMoves(BoardManager manager)
        {
            var moves = new List <Move>();

            if (manager.ActiveBlock == null)
            {
                return(moves.OrderByDescending(x => x.IsValid));
            }

            // enumerate all possible block x positions with rotations, calculate their fitness
            var rowClearings = manager.GameStats.TotalRowClearings;

            for (var rotation = 0; rotation < manager.ActiveBlock.BlockRotations; rotation++)
            {
                for (var column = -2; column < manager.NumberOfColumns; column++)
                {
                    var tempManager = new BoardManager(manager.GameBoard.DeepClone(), manager.ActiveBlock.Clone(), manager.GameStats.Clone(), null);
                    var tempBlock   = tempManager.ActiveBlock.Clone();

                    // set rotation
                    for (var i = 0; i < rotation; i++)
                    {
                        tempBlock.Move(Tetris.Engine.Move.RotateRight);
                    }

                    // set x position
                    var columnOffset = column - manager.ActiveBlock.Position.Column;

                    // create move if appropriate position
                    if (moveBlock())
                    {
                        while (tempManager.CheckBlock(tempBlock.Move(Tetris.Engine.Move.Down)))
                        {
                        }

                        // restore previous block position
                        tempManager.ActiveBlock.Merge(tempBlock.Move(Tetris.Engine.Move.Up));

                        tempManager.LockBlock();
                        tempManager.CheckBoard();
                        var rowsCleared = tempManager.GameStats.TotalRowClearings - rowClearings;
                        moves.Add(new Move
                        {
                            ColumnOffSet = columnOffset,
                            Fitness      = tempManager.CanSpawnBlock()
                            ? algorithm.CalculateFitness(tempManager.GameBoard, tempBlock.Position.Row, rowsCleared)
                            : int.MaxValue,
                            IsValid  = true,
                            Rotation = rotation
                        });
                    }

                    /////////////////////////////////////
                    bool moveBlock()
                    {
                        var step = columnOffset > 0 ? 1 : -1;
                        var move = columnOffset > 0 ? Tetris.Engine.Move.Right : Tetris.Engine.Move.Left;

                        for (var n = 0; n != columnOffset; n += step)
                        {
                            if (tempManager.CheckBlock(tempBlock.Move(move)) == false)
                            {
                                return(false);
                            }
                        }

                        return(true);
                    }
                }
            }

            return(moves.OrderByDescending(x => x.IsValid).ThenBy(x => x.Fitness));
        }