Fix wrong piecetype in GameMoveHistory
This commit is contained in:
parent
c9242fd749
commit
c318cb4ca0
5 changed files with 138 additions and 100 deletions
|
@ -25,9 +25,23 @@ namespace ChessChallenge.API
|
||||||
/// Create a new board. Note: this should not be used in the challenge,
|
/// Create a new board. Note: this should not be used in the challenge,
|
||||||
/// use the board provided in the Think method instead.
|
/// use the board provided in the Think method instead.
|
||||||
/// </summary>
|
/// </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();
|
moveGen = new APIMoveGen();
|
||||||
cachedLegalMoves = Array.Empty<Move>();
|
cachedLegalMoves = Array.Empty<Move>();
|
||||||
cachedLegalCaptureMoves = Array.Empty<Move>();
|
cachedLegalCaptureMoves = Array.Empty<Move>();
|
||||||
|
@ -49,11 +63,7 @@ namespace ChessChallenge.API
|
||||||
// Init rep history
|
// Init rep history
|
||||||
repetitionHistory = new HashSet<ulong>(board.RepetitionPositionHistory);
|
repetitionHistory = new HashSet<ulong>(board.RepetitionPositionHistory);
|
||||||
GameRepetitionHistory = repetitionHistory.ToArray();
|
GameRepetitionHistory = repetitionHistory.ToArray();
|
||||||
GameRepetitionHistory.Reverse();
|
|
||||||
repetitionHistory.Remove(board.ZobristKey);
|
repetitionHistory.Remove(board.ZobristKey);
|
||||||
|
|
||||||
// Init game moves history
|
|
||||||
GameMoveHistory = board.AllGameMoves.Select(m => new Move(MoveUtility.GetMoveNameUCI(m), this)).ToArray();
|
|
||||||
}
|
}
|
||||||
|
|
||||||
/// <summary>
|
/// <summary>
|
||||||
|
|
|
@ -142,9 +142,7 @@ namespace ChessChallenge.Application
|
||||||
|
|
||||||
Move GetBotMove()
|
Move GetBotMove()
|
||||||
{
|
{
|
||||||
// Board b = new Board();
|
API.Board botBoard = new(board);
|
||||||
// b.LoadPosition(FenUtility.CurrentFen(board));
|
|
||||||
API.Board botBoard = new(new(board));
|
|
||||||
try
|
try
|
||||||
{
|
{
|
||||||
API.Timer timer = new(PlayerToMove.TimeRemainingMs);
|
API.Timer timer = new(PlayerToMove.TimeRemainingMs);
|
||||||
|
|
|
@ -268,12 +268,13 @@ namespace ChessChallenge.Application
|
||||||
static void MiscTest()
|
static void MiscTest()
|
||||||
{
|
{
|
||||||
Console.WriteLine("Running Misc Tests");
|
Console.WriteLine("Running Misc Tests");
|
||||||
|
|
||||||
|
// Captures
|
||||||
var board = new Chess.Board();
|
var board = new Chess.Board();
|
||||||
board.LoadPosition("1q3rk1/P5p1/4p2p/2ppP1N1/5Qb1/1PP5/7P/2R2RK1 w - - 0 28");
|
board.LoadPosition("1q3rk1/P5p1/4p2p/2ppP1N1/5Qb1/1PP5/7P/2R2RK1 w - - 0 28");
|
||||||
boardAPI = new(board);
|
boardAPI = new(board);
|
||||||
Assert(boardAPI.IsWhiteToMove, "Colour to move wrong");
|
Assert(boardAPI.IsWhiteToMove, "Colour to move wrong");
|
||||||
|
|
||||||
//var moves = boardAPI.GetLegalMoves();
|
|
||||||
var captures = boardAPI.GetLegalMoves(true);
|
var captures = boardAPI.GetLegalMoves(true);
|
||||||
Assert(captures.Length == 4, "Captures wrong");
|
Assert(captures.Length == 4, "Captures wrong");
|
||||||
int numTested = 0;
|
int numTested = 0;
|
||||||
|
@ -308,6 +309,20 @@ namespace ChessChallenge.Application
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
Assert(numTested == 4, "Target square wrong");
|
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()
|
static void MoveGenTest()
|
||||||
|
|
|
@ -59,7 +59,8 @@ namespace ChessChallenge.Chess
|
||||||
public GameState currentGameState;
|
public GameState currentGameState;
|
||||||
|
|
||||||
public List<Move> AllGameMoves;
|
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
|
// piece count excluding pawns and kings
|
||||||
public int totalPieceCountWithoutPawnsAndKings;
|
public int totalPieceCountWithoutPawnsAndKings;
|
||||||
|
@ -72,16 +73,13 @@ namespace ChessChallenge.Chess
|
||||||
{
|
{
|
||||||
if (source != null)
|
if (source != null)
|
||||||
{
|
{
|
||||||
string fen = FenUtility.CurrentFen(source);
|
LoadPosition(source.StartPositionInfo);
|
||||||
LoadPosition(fen);
|
|
||||||
|
|
||||||
RepetitionPositionHistory = new(source.RepetitionPositionHistory);
|
for (int i = 0; i < source.AllGameMoves.Count; i++)
|
||||||
AllGameMoves = new(source.AllGameMoves);
|
{
|
||||||
|
MakeMove(source.AllGameMoves[i], false);
|
||||||
currentGameState = source.currentGameState;
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
@ -470,9 +468,13 @@ namespace ChessChallenge.Chess
|
||||||
// Load custom position from fen string
|
// Load custom position from fen string
|
||||||
public void LoadPosition(string fen)
|
public void LoadPosition(string fen)
|
||||||
{
|
{
|
||||||
|
LoadPosition(FenUtility.PositionFromFen(fen));
|
||||||
|
}
|
||||||
|
|
||||||
|
public void LoadPosition(FenUtility.PositionInfo posInfo)
|
||||||
|
{
|
||||||
|
StartPositionInfo = posInfo;
|
||||||
Initialize();
|
Initialize();
|
||||||
GameStartFen = fen;
|
|
||||||
FenUtility.PositionInfo posInfo = FenUtility.PositionFromFen(fen);
|
|
||||||
|
|
||||||
// Load pieces into board array and piece lists
|
// Load pieces into board array and piece lists
|
||||||
for (int squareIndex = 0; squareIndex < 64; squareIndex++)
|
for (int squareIndex = 0; squareIndex < 64; squareIndex++)
|
||||||
|
|
|
@ -1,4 +1,6 @@
|
||||||
using System.Collections.Generic;
|
using System;
|
||||||
|
using System.Collections.Generic;
|
||||||
|
using System.Collections.ObjectModel;
|
||||||
|
|
||||||
namespace ChessChallenge.Chess
|
namespace ChessChallenge.Chess
|
||||||
{
|
{
|
||||||
|
@ -11,72 +13,7 @@ namespace ChessChallenge.Chess
|
||||||
public static PositionInfo PositionFromFen(string fen)
|
public static PositionInfo PositionFromFen(string fen)
|
||||||
{
|
{
|
||||||
|
|
||||||
PositionInfo loadedPositionInfo = new PositionInfo();
|
PositionInfo loadedPositionInfo = new(fen);
|
||||||
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);
|
|
||||||
}
|
|
||||||
return loadedPositionInfo;
|
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
|
// Castling rights
|
||||||
public bool whiteCastleKingside;
|
public readonly bool whiteCastleKingside;
|
||||||
public bool whiteCastleQueenside;
|
public readonly bool whiteCastleQueenside;
|
||||||
public bool blackCastleKingside;
|
public readonly bool blackCastleKingside;
|
||||||
public bool blackCastleQueenside;
|
public readonly bool blackCastleQueenside;
|
||||||
// En passant file (1 is a-file, 8 is h-file, 0 means none)
|
// En passant file (1 is a-file, 8 is h-file, 0 means none)
|
||||||
public int epFile;
|
public readonly int epFile;
|
||||||
public bool whiteToMove;
|
public readonly bool whiteToMove;
|
||||||
// Number of half-moves since last capture or pawn advance
|
// Number of half-moves since last capture or pawn advance
|
||||||
// (starts at 0 and increments after each player's move)
|
// (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
|
// Total number of moves played in the game
|
||||||
// (starts at 1 and increments after black's move)
|
// (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);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
Loading…
Add table
Add a link
Reference in a new issue