Explanation
I have a list of all possible current moves in a position. At each node, I want to then generate all possible moves and continue. The problem is that my code is modifying the list of moves in the node above. At least I think this is the case!
I am open to completely changing the way I handle moves, as I feel this isn't very efficient since I have a struct for every move.
Output
This is the current output.
PS D:\Users\kmont\Desktop\ChessEngine> dotnet run
Number of moves at depth 1 is 4. It is White's turn.
Number of moves at depth 2 is 4. It is Black's turn. Previous move was knight to a3
Unhandled exception. System.InvalidOperationException: Collection was modified; enumeration operation may not execute.
at System.Collections.Generic.List`1.Enumerator.MoveNextRare()
at System.Collections.Generic.List`1.Enumerator.MoveNext()
at Program.search(Int32 depth, Board board, String prevMove) in D:\Users\kmont\Desktop\ChessEngine\Main\main.cs:line 55
at Program.search(Int32 depth, Board board, String prevMove) in D:\Users\kmont\Desktop\ChessEngine\Main\main.cs:line 60
at Program.Main(String[] args) in D:\Users\kmont\Desktop\ChessEngine\Main\main.cs:line 33
Code
The Move Struct:
public struct Move{
public Piece.Type pieceType;
public UInt64 piece;
public UInt64 moveTo;
public int color;
public bool quiet;
public UInt64 capturedPiece;
public int capturedColor;
}
Search function:
public static void search(int depth, Board board, string prevMove = "nothing"){
// If at the end of the tree, return.
depth++;
if (depth == maxDepth) return;
Console.Write("Number of moves at depth {0} is {1}. It is {2}'s turn.", depth, board.allMoves.Count, board.color == 0 ? "White" : "Black");
if (prevMove != "nothing") Console.WriteLine(" Previous move was knight to " + prevMove);
else Console.WriteLine("");
// Uncomment below line for a list of all possible moves.
//if (true) foreach (Board.Move move in board.allMoves) Console.WriteLine(String.Format(" {0} {1} on square {2} can move to {3}.", move.color == 0 ? "White" : "Black", move.pieceType.ToString(), help.square(move.piece), help.square(move.moveTo)));
foreach (Board.Move move in board.allMoves){
Board newBoard = board;
newBoard.color = 1 - board.color;
initialiseBoard(newBoard);
newBoard = makeMove(newBoard, move);
search(depth, newBoard, help.square(move.moveTo));
}
}
Make move function:
public static Board makeMove(Board board, Board.Move move){
string moveColor = move.color == 0 ? "White" : "Black";
string boardColor = board.color == 0 ? "White" : "Black";
string pmove = help.square(move.moveTo);
//Console.WriteLine(String.Format(" Making {0} move {2}: It is {1}'s turn.", moveColor, boardColor, pmove));
Board toReturn = board;
// Remove piece from board
if (toReturn.color == 0 & move.color == 0){
if (move.pieceType == Piece.Type.Knight){
toReturn.WhiteKnightsBitboard &= ~move.piece; // Get rid of piece on board
toReturn.WhiteKnightsBitboard |= move.moveTo; // Add piece to board
}
}
else if (toReturn.color == 1 & move.color == 1){
if (move.pieceType == Piece.Type.Knight){
toReturn.BlackKnightsBitboard &= ~move.piece;
toReturn.BlackKnightsBitboard |= move.moveTo;
}
}
Game.node++; // To count nodes
return toReturn;
}
Initialise Board function:
static void initialiseBoard(Board board){
BoardOperations.updatePieces(board); // Sets all pieces and finds empty squares
board.generateAttackSquares(board); // Finds white knight moves and puts them into board.allMoves
}