Fix wrong piecetype in GameMoveHistory

This commit is contained in:
Sebastian Lague 2023-07-25 15:47:59 +02:00
parent c9242fd749
commit c318cb4ca0
5 changed files with 138 additions and 100 deletions

View file

@ -25,9 +25,23 @@ namespace ChessChallenge.API
/// Create a new board. Note: this should not be used in the challenge,
/// use the board provided in the Think method instead.
/// </summary>
public Board(Chess.Board board)
public Board(Chess.Board boardSource)
{
this.board = board;
// Clone board and create game move history
board = new Chess.Board();
board.LoadPosition(boardSource.StartPositionInfo);
GameMoveHistory = new Move[boardSource.AllGameMoves.Count];
for (int i = 0; i < boardSource.AllGameMoves.Count; i ++)
{
Chess.Move move = boardSource.AllGameMoves[i];
int movePieceType = PieceHelper.PieceType(board.Square[move.StartSquareIndex]);
int capturePieceType = PieceHelper.PieceType(board.Square[move.TargetSquareIndex]);
GameMoveHistory[i] = new Move(move, movePieceType, capturePieceType);
board.MakeMove(move, false);
}
// Init move gen
moveGen = new APIMoveGen();
cachedLegalMoves = Array.Empty<Move>();
cachedLegalCaptureMoves = Array.Empty<Move>();
@ -49,11 +63,7 @@ namespace ChessChallenge.API
// Init rep history
repetitionHistory = new HashSet<ulong>(board.RepetitionPositionHistory);
GameRepetitionHistory = repetitionHistory.ToArray();
GameRepetitionHistory.Reverse();
repetitionHistory.Remove(board.ZobristKey);
// Init game moves history
GameMoveHistory = board.AllGameMoves.Select(m => new Move(MoveUtility.GetMoveNameUCI(m), this)).ToArray();
}
/// <summary>

View file

@ -142,9 +142,7 @@ namespace ChessChallenge.Application
Move GetBotMove()
{
// Board b = new Board();
// b.LoadPosition(FenUtility.CurrentFen(board));
API.Board botBoard = new(new(board));
API.Board botBoard = new(board);
try
{
API.Timer timer = new(PlayerToMove.TimeRemainingMs);

View file

@ -268,12 +268,13 @@ namespace ChessChallenge.Application
static void MiscTest()
{
Console.WriteLine("Running Misc Tests");
// Captures
var board = new Chess.Board();
board.LoadPosition("1q3rk1/P5p1/4p2p/2ppP1N1/5Qb1/1PP5/7P/2R2RK1 w - - 0 28");
boardAPI = new(board);
Assert(boardAPI.IsWhiteToMove, "Colour to move wrong");
//var moves = boardAPI.GetLegalMoves();
var captures = boardAPI.GetLegalMoves(true);
Assert(captures.Length == 4, "Captures wrong");
int numTested = 0;
@ -308,6 +309,20 @@ namespace ChessChallenge.Application
}
}
Assert(numTested == 4, "Target square wrong");
// Game moves
string startPos = "r1bqkbnr/pppppppp/2n5/8/4P3/8/PPPP1PPP/RNBQKBNR w KQkq - 1 2";
board.LoadPosition(startPos);
board.MakeMove(MoveUtility.GetMoveFromUCIName("e4e5", board), false);
board.MakeMove(MoveUtility.GetMoveFromUCIName("c6e5", board), false);
var b = new Chess.Board(board);
boardAPI = new(b);
Assert(boardAPI.GameMoveHistory[0].MovePieceType is PieceType.Pawn, "Wrong game move history");
Assert(boardAPI.GameMoveHistory[0].CapturePieceType is PieceType.None, "Wrong game move history");
Assert(boardAPI.GameMoveHistory[1].MovePieceType is PieceType.Knight, "Wrong game move history");
Assert(boardAPI.GameMoveHistory[1].CapturePieceType is PieceType.Pawn, "Wrong game move history");
Assert(boardAPI.GameStartFenString == startPos, "Wrong game start fen");
Assert(boardAPI.GetFenString() == "r1bqkbnr/pppppppp/8/4n3/8/8/PPPP1PPP/RNBQKBNR w KQkq - 0 3", "Wrong game fen");
}
static void MoveGenTest()

View file

@ -59,7 +59,8 @@ namespace ChessChallenge.Chess
public GameState currentGameState;
public List<Move> AllGameMoves;
public string GameStartFen { get; private set; }
public string GameStartFen => StartPositionInfo.fen;
public FenUtility.PositionInfo StartPositionInfo;
// piece count excluding pawns and kings
public int totalPieceCountWithoutPawnsAndKings;
@ -72,16 +73,13 @@ namespace ChessChallenge.Chess
{
if (source != null)
{
string fen = FenUtility.CurrentFen(source);
LoadPosition(fen);
RepetitionPositionHistory = new(source.RepetitionPositionHistory);
AllGameMoves = new(source.AllGameMoves);
currentGameState = source.currentGameState;
LoadPosition(source.StartPositionInfo);
for (int i = 0; i < source.AllGameMoves.Count; i++)
{
MakeMove(source.AllGameMoves[i], false);
}
}
}
@ -470,9 +468,13 @@ namespace ChessChallenge.Chess
// Load custom position from fen string
public void LoadPosition(string fen)
{
LoadPosition(FenUtility.PositionFromFen(fen));
}
public void LoadPosition(FenUtility.PositionInfo posInfo)
{
StartPositionInfo = posInfo;
Initialize();
GameStartFen = fen;
FenUtility.PositionInfo posInfo = FenUtility.PositionFromFen(fen);
// Load pieces into board array and piece lists
for (int squareIndex = 0; squareIndex < 64; squareIndex++)

View file

@ -1,4 +1,6 @@
using System.Collections.Generic;
using System;
using System.Collections.Generic;
using System.Collections.ObjectModel;
namespace ChessChallenge.Chess
{
@ -11,72 +13,7 @@ namespace ChessChallenge.Chess
public static PositionInfo PositionFromFen(string fen)
{
PositionInfo loadedPositionInfo = new PositionInfo();
string[] sections = fen.Split(' ');
int file = 0;
int rank = 7;
foreach (char symbol in sections[0])
{
if (symbol == '/')
{
file = 0;
rank--;
}
else
{
if (char.IsDigit(symbol))
{
file += (int)char.GetNumericValue(symbol);
}
else
{
int pieceColour = (char.IsUpper(symbol)) ? PieceHelper.White : PieceHelper.Black;
int pieceType = char.ToLower(symbol) switch
{
'k' => PieceHelper.King,
'p' => PieceHelper.Pawn,
'n' => PieceHelper.Knight,
'b' => PieceHelper.Bishop,
'r' => PieceHelper.Rook,
'q' => PieceHelper.Queen,
_ => PieceHelper.None
};
loadedPositionInfo.squares[rank * 8 + file] = pieceType | pieceColour;
file++;
}
}
}
loadedPositionInfo.whiteToMove = (sections[1] == "w");
string castlingRights = sections[2];
loadedPositionInfo.whiteCastleKingside = castlingRights.Contains("K");
loadedPositionInfo.whiteCastleQueenside = castlingRights.Contains("Q");
loadedPositionInfo.blackCastleKingside = castlingRights.Contains("k");
loadedPositionInfo.blackCastleQueenside = castlingRights.Contains("q");
if (sections.Length > 3)
{
string enPassantFileName = sections[3][0].ToString();
if (BoardHelper.fileNames.Contains(enPassantFileName))
{
loadedPositionInfo.epFile = BoardHelper.fileNames.IndexOf(enPassantFileName) + 1;
}
}
// Half-move clock
if (sections.Length > 4)
{
int.TryParse(sections[4], out loadedPositionInfo.fiftyMovePlyCount);
}
// Full move number
if (sections.Length > 5)
{
int.TryParse(sections[5], out loadedPositionInfo.moveCount);
}
PositionInfo loadedPositionInfo = new(fen);
return loadedPositionInfo;
}
@ -273,27 +210,103 @@ namespace ChessChallenge.Chess
}
}
public class PositionInfo
public readonly struct PositionInfo
{
public int[] squares;
public readonly string fen;
public readonly ReadOnlyCollection<int> squares;
// Castling rights
public bool whiteCastleKingside;
public bool whiteCastleQueenside;
public bool blackCastleKingside;
public bool blackCastleQueenside;
public readonly bool whiteCastleKingside;
public readonly bool whiteCastleQueenside;
public readonly bool blackCastleKingside;
public readonly bool blackCastleQueenside;
// En passant file (1 is a-file, 8 is h-file, 0 means none)
public int epFile;
public bool whiteToMove;
public readonly int epFile;
public readonly bool whiteToMove;
// Number of half-moves since last capture or pawn advance
// (starts at 0 and increments after each player's move)
public int fiftyMovePlyCount;
public readonly int fiftyMovePlyCount;
// Total number of moves played in the game
// (starts at 1 and increments after black's move)
public int moveCount;
public readonly int moveCount;
public PositionInfo()
public PositionInfo(string fen)
{
squares = new int[64];
this.fen = fen;
int[] squarePieces = new int[64];
string[] sections = fen.Split(' ');
int file = 0;
int rank = 7;
foreach (char symbol in sections[0])
{
if (symbol == '/')
{
file = 0;
rank--;
}
else
{
if (char.IsDigit(symbol))
{
file += (int)char.GetNumericValue(symbol);
}
else
{
int pieceColour = (char.IsUpper(symbol)) ? PieceHelper.White : PieceHelper.Black;
int pieceType = char.ToLower(symbol) switch
{
'k' => PieceHelper.King,
'p' => PieceHelper.Pawn,
'n' => PieceHelper.Knight,
'b' => PieceHelper.Bishop,
'r' => PieceHelper.Rook,
'q' => PieceHelper.Queen,
_ => PieceHelper.None
};
squarePieces[rank * 8 + file] = pieceType | pieceColour;
file++;
}
}
}
squares = new(squarePieces);
whiteToMove = (sections[1] == "w");
string castlingRights = sections[2];
whiteCastleKingside = castlingRights.Contains('K');
whiteCastleQueenside = castlingRights.Contains('Q');
blackCastleKingside = castlingRights.Contains('k');
blackCastleQueenside = castlingRights.Contains('q');
// Default values
epFile = 0;
fiftyMovePlyCount = 0;
moveCount = 0;
if (sections.Length > 3)
{
string enPassantFileName = sections[3][0].ToString();
if (BoardHelper.fileNames.Contains(enPassantFileName))
{
epFile = BoardHelper.fileNames.IndexOf(enPassantFileName) + 1;
}
}
// Half-move clock
if (sections.Length > 4)
{
int.TryParse(sections[4], out fiftyMovePlyCount);
}
// Full move number
if (sections.Length > 5)
{
int.TryParse(sections[5], out moveCount);
}
}
}
}