/** * #function SingleBot::GetSingleMove | * @author JavaComSci | * @desc need desc here TODO | * @header public override List<...> GetSingleMove(Board, List<Block>, bool) | * @param int[][] board : current enviornment | * @param List<Block> blocks : contains the list of all the blocks to try to fit in this location | * @returns List<...> bestPiecePlacementOfCurrentBlock : contains the list of the indicies * of where the piece would be on the board | */ public List <Tuple <int, int> > GetSingleMove1(Board board, List <List <Block> > allBotBlocks, bool allRotations = false) { List <Block> blocks = allBotBlocks[0]; Console.WriteLine("BOARD"); botInfoPrinter.PrintMultiDimArr(board.board); Console.WriteLine("RECIEVED PIECE"); botInfoPrinter.PrintJaggedArr(blocks[0].data); // get the max height of each column of the baord board.FindMaxHeights(); // has the information about all the compatible pieces for a given block Dictionary <Block, List <Tuple <int, List <Tuple <int, int> >, int, int> > > allBlocksPossible = new Dictionary <Block, List <Tuple <int, List <Tuple <int, int> >, int, int> > >(); int blockCount = 0; if (blocks.Count >= 1) { shapeColor = blocks[0].color; } // test out each of the pieces foreach (Block block in blocks) { // check to make sure that each block is valid bool blockValid = block.CheckValidity(); // block is invalid if (!blockValid) { throw new Exception("Shape formation is incorrect"); } // compatible pieces for a single block // has all the positions compatible for this piece with the rotation, location on board, area covered, and number of lines that can be cleared List <Tuple <int, List <Tuple <int, int> >, int, int> > compatiblePieces = new List <Tuple <int, List <Tuple <int, int> >, int, int> >(); // get the fit of the board with the area and whether a piece can clear a line compatiblePieces.AddRange(getFit(board, block, 1)); block.data = block.RotateMatrix(); compatiblePieces.AddRange(getFit(board, block, 2)); block.data = block.RotateMatrix(); compatiblePieces.AddRange(getFit(board, block, 3)); block.data = block.RotateMatrix(); compatiblePieces.AddRange(getFit(board, block, 4)); if (allRotations) { block.data = block.RotateMatrix(); } // compatible pieces has all the pieces that are compatible with the board and has the information about the rotation, location on board, area covered, and if that piece can clear a line compatiblePieces.Sort((x, y) => { // sort by whether a line has been cleared and puts those first if there is int result = y.Item4.CompareTo(x.Item4); // sort by the area covered return(result == 0 ? y.Item3.CompareTo(x.Item3) : result); }); // the current piece cannot even be placed so must return null if (compatiblePieces.Count == 0 && blockCount == 0) { return(null); } blockCount++; allBlocksPossible[block] = compatiblePieces; } // get the best piece of the block that is the first one Tuple <int, List <Tuple <int, int> >, int, int> bestPieceOfCurrentBlock = allBlocksPossible[blocks[0]][0]; // placement of this block that is the best of the current block List <Tuple <int, int> > bestPiecePlacementOfCurrentBlock = bestPieceOfCurrentBlock.Item2; // if the best current piece doesnt clear any lines, need to find one that does clear lines if (bestPieceOfCurrentBlock.Item4 == 0 && blocks.Count > 1) { // does not clear any lines so need to look for another candidate and choose the next best spot for this block // find the next piece that clears lines Tuple <int, List <Tuple <int, int> >, int, int> bestPieceOfNextBlock = allBlocksPossible[blocks[1]][0]; // next next piece that clears lines Tuple <int, List <Tuple <int, int> >, int, int> bestPieceOfNextNextBlock = allBlocksPossible.Count > 2 ? allBlocksPossible[blocks[2]][0] : null; // Console.WriteLine("NEXT PIECE " + bestPieceOfNextNextBlock.Item4); // the next piece is able to clear lines if (bestPieceOfNextBlock.Item4 > 0) { // Console.WriteLine("I AM HEREHEHEH LOOKING AT THE NEXT PIECE!\n"); // create a new copy of the board so that it can run through the steps for clearing lines again int [,] copiedBoard = board.CopyBoard(board.board); // add the pieces to this board to where it has the new information copiedBoard = board.FillBoardWithPieceConsidered(copiedBoard, bestPieceOfNextBlock.Item2); // check to see if there is anything the current piece can place so do another search with the new info List <Tuple <int, List <Tuple <int, int> >, int, int> > compatiblePiecesForCurrentPieceAfterPiece1 = new List <Tuple <int, List <Tuple <int, int> >, int, int> >(); // set up new board Board cBoard = new Board(board.board.GetLength(0), board.board.GetLength(1)); cBoard.board = copiedBoard; cBoard.FindMaxHeights(); // get the fit of the board with the area and whether a piece can clear a line compatiblePiecesForCurrentPieceAfterPiece1.AddRange(getFit(cBoard, blocks[0], 1)); blocks[0].data = blocks[0].RotateMatrix(); compatiblePiecesForCurrentPieceAfterPiece1.AddRange(getFit(cBoard, blocks[0], 2)); blocks[0].data = blocks[0].RotateMatrix(); compatiblePiecesForCurrentPieceAfterPiece1.AddRange(getFit(cBoard, blocks[0], 3)); blocks[0].data = blocks[0].RotateMatrix(); compatiblePiecesForCurrentPieceAfterPiece1.AddRange(getFit(cBoard, blocks[0], 4)); if (allRotations) { blocks[0].data = blocks[0].RotateMatrix(); } // compatible pieces has all the pieces that are compatible with the board and has the information about the rotation, location on board, area covered, and if that piece can clear a line compatiblePiecesForCurrentPieceAfterPiece1.Sort((x, y) => { // sort by whether a line has been cleared and puts those first if there is int result = y.Item4.CompareTo(x.Item4); // sort by the area covered return(result == 0 ? y.Item3.CompareTo(x.Item3) : result); }); // placement of this block that is the best of the current block bestPiecePlacementOfCurrentBlock = compatiblePiecesForCurrentPieceAfterPiece1[0].Item2; } else if (bestPieceOfNextNextBlock != null && bestPieceOfNextNextBlock.Item4 > 0) { // Console.WriteLine("I AM A NEXT NEXT SHAPE\n\n\n\n"); // check 2 shapes from the current shape // create a new copy of the board so that it can run through the steps for clearing lines again int [,] copiedBoard = board.CopyBoard(board.board); // add the pieces to this board to where it has the new information copiedBoard = board.FillBoardWithPieceConsidered(copiedBoard, bestPieceOfNextNextBlock.Item2); // check to see if there is anything the current piece can place so do another search with the new info List <Tuple <int, List <Tuple <int, int> >, int, int> > compatiblePiecesForCurrentPieceAfterPiece2 = new List <Tuple <int, List <Tuple <int, int> >, int, int> >(); // set up new board Board cBoard = new Board(board.board.GetLength(0), board.board.GetLength(1)); cBoard.board = copiedBoard; cBoard.FindMaxHeights(); // get the fit of the board with the area and whether a piece can clear a line compatiblePiecesForCurrentPieceAfterPiece2.AddRange(getFit(cBoard, blocks[0], 1)); blocks[0].data = blocks[0].RotateMatrix(); compatiblePiecesForCurrentPieceAfterPiece2.AddRange(getFit(cBoard, blocks[0], 2)); blocks[0].data = blocks[0].RotateMatrix(); compatiblePiecesForCurrentPieceAfterPiece2.AddRange(getFit(cBoard, blocks[0], 3)); blocks[0].data = blocks[0].RotateMatrix(); compatiblePiecesForCurrentPieceAfterPiece2.AddRange(getFit(cBoard, blocks[0], 4)); if (allRotations) { blocks[0].data = blocks[0].RotateMatrix(); } // compatible pieces has all the pieces that are compatible with the board and has the information about the rotation, location on board, area covered, and if that piece can clear a line compatiblePiecesForCurrentPieceAfterPiece2.Sort((x, y) => { // sort by whether a line has been cleared and puts those first if there is int result = y.Item4.CompareTo(x.Item4); // sort by the area covered return(result == 0 ? y.Item3.CompareTo(x.Item3) : result); }); // placement of this block that is the best of the current block bestPiecePlacementOfCurrentBlock = compatiblePiecesForCurrentPieceAfterPiece2[0].Item2; } } // Console.WriteLine("BEST PIECE FOR BOARD"); // botInfoPrinter.PrintPositions(bestPiecePlacementOfCurrentBlock); Console.WriteLine("BOARD WITH PIECE"); botInfoPrinter.PrintBoardWithPiece(board.board, bestPiecePlacementOfCurrentBlock); return(bestPiecePlacementOfCurrentBlock); }