I made a fully functional chess game in Unity using C#. Now i want to add AI, for the chess engine i went with Stockfish. I got the engine inside the game but it does nothing because it cant communicate with the board.
To communicate i need to make a FEN string per row, starting on the top left, the FEN string looks like this:
rnbqkbnr/pppppppp/8/8/8/8/PPPPPPPP/RNBQKBNR w KQkq - 0 1
lower case are black pieces, upper case white pieces, the numbers are black spaces, w means white turn next, KQkq means that castling in available, - means en passant is available and 0 1 number of moves.
Does anyone know of a tutorial, or tips to create and manipulate strings to make the FEN string?
I will paste the code i have done so far towards the Stockfish Process, i haven't done anything related to the FEN string because i don't really know how to start it.
Any links or tips are welcome
void RunProcess()
{
ProcessStartInfo startInfo = new ProcessStartInfo();
startInfo.UseShellExecute = false;
startInfo.RedirectStandardInput = true;
startInfo.RedirectStandardOutput = true;
startInfo.RedirectStandardError = false;
startInfo.CreateNoWindow = true;
startInfo.FileName = Application.streamingAssetsPath + "/stockfish_9_x64.exe";
Process process = new Process();
process.StartInfo = startInfo;
process.Start();
string output;
process.StandardInput.WriteLine("uci");
process.StandardInput.WriteLine("isready");
process.StandardInput.WriteLine("position fen rnbqkbnr/pppppppp/8/8/8/8/PPPPPPPP/RNBQKBNR w KQkq - 0 1");
process.StandardInput.WriteLine("go");
process.StandardInput.WriteLine("stop");
process.StandardInput.WriteLine("quit");
do
{
output = process.StandardOutput.ReadLine();
} while (!output.Contains("move"));
UnityEngine.Debug.Log(output);
}
void OnMouseDown()
{
RunProcess();
}
Just to get the basic piece, you could do something like (note: not tested):
public enum ChessPieces
{
King, Queen, Rook, // ... etc.
}
public class ChessPiece : MonoBehavior
{
public string FenId { get; }
private readonly Dictionary<ChessPiece, string> FenIds = {
{ ChessPieces.King, "K" },
{ ChessPieces.Queen, "Q" },
// ... etc.
};
// assuming you create the set of pieces programatically, use this constructor
public ChessPiece(ChessPiece piece, ChessColor color)
{
FenId = color == ChessColor.Black
? FenIds[piece].ToLower()
: FenIds[piece].ToUpper();
}
}
Then, assuming you are storing your board in an array of rows, to dump the layout into a string I'd probably override ToString
on my ChessBoard
class (also not tested):
// somewhere in your code set the board up
_chessBoard.Rows.Add(new [] {
new ChessPiece(ChessPieces.Rook, ChessColor.Black),
new ChessPiece(ChessPieces.Knight, ChessColor.Black),
// ... etc.
})
_chessBoard.Rows.Add(new [] { /* next row ... */ });
// ... etc.
// to create your output, put this into the override of ToString:
var output = ""; // should be StringBuilder, but for clarity and since this isn't likely performance limiting...
var rowIndex = 0;
foreach (var row in _chessBoard.Rows)
{
rowIndex++;
var blankSpaces = 0;
foreach(var piece in row)
{
if (piece == null)
{
blankSpaces++;
}
else
{
output += blankSpaces == 0
? piece.FenId
: string.Format("{0}{1}", blankspaces, piece.FenId);
blankSpaces = 0;
}
if (blankSpaces > 0)
{
output += blankSpaces;
}
}
if (rowIndex != 8)
{
output += "/";
}
}
At this point you've got your basic layout in a string and you should have the basic idea for adding the other FEN fields.
I should note that I've selected a collection of arrays for storing your board. That probably isn't the most efficient storage mechanism (i.e. in the best case you're storing 50% empty values, which will only increase as the game progresses), but since we're only talking about 64 items total we're probably okay on memory.