Skip to content

Commit

Permalink
Minor bug fixes, settings.txt was in .gitignore, rebased to fix
Browse files Browse the repository at this point in the history
  • Loading branch information
Sargates authored and Sargates committed Aug 20, 2023
1 parent 53aaf72 commit 9d987eb
Show file tree
Hide file tree
Showing 5 changed files with 50 additions and 49 deletions.
2 changes: 1 addition & 1 deletion readme.md
Original file line number Diff line number Diff line change
@@ -1,7 +1,7 @@
# Chess Bot (C#)
## By Nick Glenn

A chess bot written in C#, using the Raylib_cs library
A chess bot written in C#, using the Raylib_cs library\
Heavily influenced by Sebastian Lague's "Chess AI" mini-series

Requires .NET 6.0 and up
Expand Down
10 changes: 5 additions & 5 deletions src/Application/Core/Controller.cs
Original file line number Diff line number Diff line change
Expand Up @@ -189,7 +189,7 @@ public void HandleMouseInput() {
//* Case 2 is satisfied by this point, do additional checks to get desired behavior
view.ui.SelectedIndex = squareClicked;
view.ui.MovesForSelected = new Move[0]; // Reset moves because we're going to potentially recalculate them anyways
if (! ((model.humanColor >> 1) == 1 && clickedPiece.Color == Piece.White || (model.humanColor & 1) == 1 && clickedPiece.Color == Piece.Black)) { //! Case 2a
if (! ((model.humanColor >> 1) == 1 && clickedPiece.Color == Piece.White || (model.humanColor & 1) == 1 && clickedPiece.Color == Piece.Black) && ! model.SuspendPlay) { //! Case 2a
return;
} //* Passes guard clause if square clicked is a human color
if (! (!model.enforceColorToMove || model.enforceColorToMove && (model.board.whiteToMove ? Piece.White : Piece.Black) == clickedPiece.Color)) { //! Case 2b
Expand Down Expand Up @@ -220,7 +220,7 @@ public void HandleMouseInput() {
return;
}
}
if (mouseClickInfo[3] != -1) { //* Release of right click
if (mouseClickInfo[3] != -1 && mouseClickInfo[2] != -1) { //* Release of right click
if (mouseClickInfo[0] == -1) {
if (mouseClickInfo[2] == mouseClickInfo[3]) { //* Should highlight square
view.ui.highlightedSquares[mouseClickInfo[2]] = ! view.ui.highlightedSquares[mouseClickInfo[2]];
Expand Down Expand Up @@ -266,18 +266,18 @@ public void HandleKeyboardInput() {
if ((model.board.currentStateNode.Previous?.Previous == null)) { break; }

model.DoublePrevState();
} else { // otherwise undo a single move
} else { //* otherwise undo a single move
model.SinglePrevState();
}
view.ui.DeselectActiveSquare();
break;
}
case (int) KeyboardKey.KEY_X :{
if ((model.ActivePlayer.Computer?.IsSearching ?? false)) { break; }
// If there is exactly one human, undo two moves
//* If there is exactly one human, redo two moves
if ((((model.humanColor >> 0) & 1) ^ ((model.humanColor >> 1) & 1)) == 1) {
model.DoubleNextState();
} else { // otherwise undo a single move
} else { //* otherwise undo a single move
model.SingleNextState();
}
view.ui.DeselectActiveSquare();
Expand Down
81 changes: 42 additions & 39 deletions src/Application/Core/Model.cs
Original file line number Diff line number Diff line change
Expand Up @@ -77,48 +77,50 @@ public void AddButtons() {

// Below methods handle the changing state of the board
public void MakeMoveOnBoard(Move move, bool animate=true) {
if (move.IsNull) {
Console.WriteLine("Null move was made, assumed checkmate");
return;
}

view.ui.DeselectActiveSquare();
ActivePlayer.IsSearching = false;


Piece pieceMoved = board.GetSquare(move.StartSquare);
board.MakeMove(move);
view.TimeOfLastMove = view.fTimeElapsed;

bool opponentInCheck = MoveGenerator.IsSquareAttacked(board, board.ActiveColor == Piece.White ? board.whiteKingPos : board.blackKingPos, board.ActiveColor);
bool canOpponentRespond = MoveGenerator.GetAllMoves(board, board.ActiveColor).Length != 0; // Negated for readability

if (board.currentStateNode.Previous == null) { throw new Exception("Something went wrong"); }
Fen temp = board.currentStateNode.Previous.Value;

if (opponentInCheck && canOpponentRespond) {
temp.moveMade.moveSoundEnum = (int)SoundStates.Check;
} else
if (opponentInCheck && ! canOpponentRespond) {
temp.moveMade.moveSoundEnum = 0; // Sound is played separately if game is over
} else
if (! opponentInCheck && ! canOpponentRespond) {
temp.moveMade.moveSoundEnum = 0; // Sound is played separately if game is over
}

Debug.Assert(board.currentStateNode.Previous != null);
board.currentStateNode.Previous.Value = temp;

if (animate) { // Sounds are built in to animations, if move is not animated, play sound manually
view.ui.activeAnimations.AddRange(AnimationHelper.FromMove(temp.moveMade, pieceMoved));
bool opponentInCheck;
if (! move.IsNull) {
view.ui.DeselectActiveSquare();
ActivePlayer.IsSearching = false;


Piece pieceMoved = board.GetSquare(move.StartSquare);
board.MakeMove(move);
view.TimeOfLastMove = view.fTimeElapsed;

opponentInCheck = MoveGenerator.IsSquareAttacked(board, board.ActiveColor == Piece.White ? board.whiteKingPos : board.blackKingPos, board.ActiveColor);
bool canOpponentRespond = MoveGenerator.GetAllMoves(board, board.ActiveColor).Length != 0; // Negated for readability

if (board.currentStateNode.Previous == null) { throw new Exception("Something went wrong"); }
Fen temp = board.currentStateNode.Previous.Value;

if (opponentInCheck && canOpponentRespond) {
temp.moveMade.moveSoundEnum = (int)SoundStates.Check;
} else
if (opponentInCheck && ! canOpponentRespond) {
temp.moveMade.moveSoundEnum = 0; // Sound is played separately if game is over
} else
if (! opponentInCheck && ! canOpponentRespond) {
temp.moveMade.moveSoundEnum = 0; // Sound is played separately if game is over
}

Debug.Assert(board.currentStateNode.Previous != null);
board.currentStateNode.Previous.Value = temp;

if (animate) { // Sounds are built in to animations, if move is not animated, play sound manually
view.ui.activeAnimations.AddRange(AnimationHelper.FromMove(temp.moveMade, pieceMoved));
} else {
Raylib.PlaySound(BoardUI.sounds[board.currentStateNode.Previous.Value.moveMade.moveSoundEnum]);
}

// If opponent can't respond, fallthrough to game end handling
if (canOpponentRespond) {
return;
}
} else {
Raylib.PlaySound(BoardUI.sounds[board.currentStateNode.Previous.Value.moveMade.moveSoundEnum]);
opponentInCheck = true;
Console.WriteLine("Null move was made, assumed checkmate");
}

// If opponent can't respond, fallthrough to game end handling
if (canOpponentRespond) {
return;
}

SuspendPlay = true;

Expand Down Expand Up @@ -207,6 +209,7 @@ public void StartNewGame(string fenString=Fen.startpos, Gametype type=Gametype.H
view.ui.IsFlipped = humanColor == 0b01; // if white is not a player and black is a player
gameIndex++;
view.ui.activeAnimations.AddRange(AnimationHelper.FromBoardChange(oldBoard, board.board, 0.2f));
SuspendPlay = false;
}
public void SetPrevState() {
if (board.currentStateNode.Previous == null) { Console.WriteLine("Cannot get previous state, is null"); return; }
Expand Down
4 changes: 1 addition & 3 deletions src/Application/Gameplay/Players/UCIPlayer.cs
Original file line number Diff line number Diff line change
Expand Up @@ -60,13 +60,11 @@ public override Move Think() { // position should already be set
}
}
// GetMoves returns empty Move[] if startSquare is empty, the only reason this should happen is if the
// thread is supposed to exit. Otherwise something is actually wrong and an exception should be thrown
if (ExitFlag) { return Move.NullMove; } // This shouldnt raise checkmate when it returns
return Move.NullMove;
}

~UCIPlayer() { // In case player object ever goes out of scope
ExitFlag = true;
thread.Join();
} // Apparently deconstructors aren't inherited, kind of makes sense
}
}
2 changes: 1 addition & 1 deletion src/Engine/Move Generation/MoveGenerator.cs
Original file line number Diff line number Diff line change
Expand Up @@ -336,7 +336,7 @@ public static Move[] GetMoves(Board board, int index) { // ! check edgecases

if (! isInCheck) {
return moves.ToArray();
} //* Passes guard clause if king is checked
} //* Passes guard clause if king is in check


for (int i=moves.Count-1; i>-1; i--) { //* Check each move against needed squares to block the check
Expand Down

0 comments on commit 9d987eb

Please sign in to comment.