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)); }