From 522435f3aa5faf47b474702936254078d1484f6f Mon Sep 17 00:00:00 2001 From: Kresten Laust Date: Fri, 27 Jan 2023 00:01:17 +0100 Subject: [PATCH 1/4] - Working on improving dangersquare performance. There's a problem with the pawn's dangersquares. --- ChessForms/BoardDisplay.cs | 7 +- ChessGame.Tests/ClassicChessTest.cs | 2 +- ChessGame.Tests/DangerzoneTests.cs | 4 +- ChessGame/Chessboard.cs | 109 +++++++++++++++++++--- ChessGame/MovementPatterns/KingPattern.cs | 10 +- 5 files changed, 110 insertions(+), 22 deletions(-) diff --git a/ChessForms/BoardDisplay.cs b/ChessForms/BoardDisplay.cs index 0fcef72..6b96f72 100644 --- a/ChessForms/BoardDisplay.cs +++ b/ChessForms/BoardDisplay.cs @@ -303,13 +303,18 @@ public void InstantiateUIBoard() /// void DrawDangerzone() { - foreach (KeyValuePair> item in chessboard.Dangerzone) + foreach (KeyValuePair> item in chessboard.Dangerzone) { if (!chessboard.InsideBoard(item.Key)) { continue; } + if (item.Value.Count == 0) + { + continue; + } + ColorSquare(item.Key, DangersquareColor); } } diff --git a/ChessGame.Tests/ClassicChessTest.cs b/ChessGame.Tests/ClassicChessTest.cs index f8dba88..caba766 100644 --- a/ChessGame.Tests/ClassicChessTest.cs +++ b/ChessGame.Tests/ClassicChessTest.cs @@ -43,7 +43,7 @@ public void CheckPatternsTest() List moves = chessboard.GetMoves().ToList(); // check if the amount of moves even is correct. - Assert.IsTrue(moves.Count == possibleMoves.Count); + Assert.AreEqual(possibleMoves.Count, moves.Count); // checks if all moves are valid. foreach (var item in moves) diff --git a/ChessGame.Tests/DangerzoneTests.cs b/ChessGame.Tests/DangerzoneTests.cs index a512649..b61cab0 100644 --- a/ChessGame.Tests/DangerzoneTests.cs +++ b/ChessGame.Tests/DangerzoneTests.cs @@ -30,7 +30,7 @@ public void TestPawnDangerzone() chessboard.StartNextTurn(); // - Check dangerzones - List piecesAimingAtB2 = chessboard.Dangerzone[new Coordinate(1, 1)]; + HashSet piecesAimingAtB2 = chessboard.Dangerzone[new Coordinate(1, 1)]; // Black king aiming at B2. Assert.IsTrue(piecesAimingAtB2.Contains(blackKing)); // Right pawn aiming at B2. @@ -69,7 +69,7 @@ public void TestPawnPromotionDangerzone() chessboard.CurrentTeamTurn = TeamColor.Black; chessboard.PerformMove("c2c1R", MoveNotation.UCI); - List piecesAimingAtE1 = chessboard.Dangerzone[new Coordinate(4, 0)]; + HashSet piecesAimingAtE1 = chessboard.Dangerzone[new Coordinate(4, 0)]; // Rook aiming at E1. Assert.IsTrue(piecesAimingAtE1.Contains(chessboard[new Coordinate(2, 0)])); diff --git a/ChessGame/Chessboard.cs b/ChessGame/Chessboard.cs index 8350dfe..3b9dc98 100644 --- a/ChessGame/Chessboard.cs +++ b/ChessGame/Chessboard.cs @@ -23,7 +23,7 @@ public class Chessboard : IEquatable /// /// Describes intersection squares. An intersection square is a square which one or more pieces threaten at once. /// - public readonly Dictionary> Dangerzone; + public readonly Dictionary> Dangerzone; /// /// Previous moves, that resolve to this position. @@ -79,8 +79,11 @@ public Chessboard(Chessboard board) MovedPieces = new HashSet(board.MovedPieces); Moves = new Stack(board.Moves); - // not needed before executing move - Dangerzone = new Dictionary>(); + Dangerzone = new Dictionary>(); + foreach (var item in board.Dangerzone) + { + Dangerzone[item.Key] = new HashSet(item.Value); + } } /// @@ -100,8 +103,11 @@ public Chessboard(Chessboard board, Move move) MovedPieces = new HashSet(board.MovedPieces); Moves = new Stack(board.Moves.Reverse()); - // is refreshed in simulatemove - Dangerzone = new Dictionary>(); + Dangerzone = new Dictionary>(); + foreach (var item in board.Dangerzone) + { + Dangerzone[item.Key] = new HashSet(item.Value); + } SimulateMove(move); } @@ -121,7 +127,7 @@ public Chessboard(byte width, byte height, Gamemode gamemode) CurrentState = GameState.NotStarted; Pieces = new Dictionary(); - Dangerzone = new Dictionary>(); + Dangerzone = new Dictionary>(); Moves = new Stack(); MovedPieces = new HashSet(); } @@ -273,6 +279,8 @@ public void ExecuteMove(Move move) foreach (var singleMove in move.Submoves) { + RemoveDangerzones(singleMove.Piece); + // remove piece if (singleMove.Destination is null) { @@ -283,7 +291,7 @@ public void ExecuteMove(Move move) Coordinate destination = singleMove.Destination.Value; // Remove previous instance - if (!(singleMove.Source is null)) + if (singleMove.Source.HasValue) { Pieces.Remove(singleMove.Source.Value); } @@ -312,10 +320,12 @@ public void ExecuteMove(Move move) } } + UpdateDangerzones(move); + // TODO: Only update neccessary dangerzones. // It should be possible to only update the pieces with dangerzone on Source square, and on Destination square. // And the moved piece itself. - UpdateDangerzones(); + //UpdateDangerzones(); } /// @@ -340,7 +350,7 @@ public bool IsKingInCheck(TeamColor color) } // Get list of pieces aiming on the square the king sits on. - if (Dangerzone.TryGetValue(position, out List pieces)) + if (Dangerzone.TryGetValue(position, out HashSet pieces)) { // Returns true if any of the pieces are of opposite color. return pieces.Any(p => p.Color != color); @@ -438,8 +448,20 @@ public IEnumerable GetMovesByNotation(string notation, TeamColor player, M customNotation = true; } + // TODO: Lookup moves by piece on source tile (when known) instead of all moves. + IEnumerable movesToSearch; + + if (source.HasValue && GetPiece(source.Value) is Piece piece) + { + movesToSearch = piece.GetMoves(this); + } + else + { + movesToSearch = GetMoves(player); + } + // Look for matching moves. - foreach (var move in GetMoves(player)) + foreach (var move in movesToSearch) { // If looking for move by custom notation, return it here. if (customNotation && move.CustomNotation == notation) @@ -505,7 +527,7 @@ public Move GetMoveByNotation(string notation, TeamColor player, MoveNotation no /// public int IsDangerSquare(Coordinate position, TeamColor color) { - if (Dangerzone.TryGetValue(position, out List pieces)) + if (Dangerzone.TryGetValue(position, out HashSet pieces)) { return pieces is null ? 0 : pieces.Count(p => p.Color == color); } @@ -520,7 +542,7 @@ public int IsDangerSquare(Coordinate position, TeamColor color) /// public int GetDangerSquareSum(Coordinate position) { - if (!Dangerzone.TryGetValue(position, out List pieces)) + if (!Dangerzone.TryGetValue(position, out HashSet pieces)) { // No pieces can capture this tile. return 0; @@ -543,6 +565,67 @@ public int GetDangerSquareSum(Coordinate position) return sum; } + void RemoveDangerzones(Piece piece) + { + List emptyLists = new List(); + + foreach (var item in Dangerzone) + { + item.Value.Remove(piece); + + if (item.Value.Count == 0) + { + emptyLists.Add(item.Key); + } + } + + foreach (var item in emptyLists) + { + Dangerzone.Remove(item); + } + } + + /// + /// Run after a move has been made. + /// + /// + void UpdateDangerzones(Move move) + { + HashSet piecesAffected = new HashSet(); + for (int i = 0; i < move.Submoves.Length; i++) + { + if (move.Submoves[i].Source is Coordinate source && Dangerzone.TryGetValue(source, out HashSet piecesAimingAtSource)) + { + foreach (var piece in piecesAimingAtSource) + { + piecesAffected.Add(piece); + } + } + + if (move.Submoves[i].Destination is Coordinate destination && Dangerzone.TryGetValue(destination, out HashSet piecesAimingAtDestination)) + { + foreach (var piece in piecesAimingAtDestination) + { + piecesAffected.Add(piece); + } + } + + if (move.Submoves[i].PromotePiece is Piece promotePiece) + { + piecesAffected.Add(promotePiece); + } + else + { + piecesAffected.Add(move.Submoves[i].Piece); + } + } + + foreach (var piece in piecesAffected) + { + UpdateDangerzones(piece); + } + } + /// /// Adds new dangerzone info of piecce. /// @@ -565,7 +648,7 @@ void UpdateDangerzones(Piece piece) // Make new list of pieces aiming on this square if there isn't one already. if (!Dangerzone.ContainsKey(destination)) { - Dangerzone[destination] = new List(); + Dangerzone[destination] = new HashSet(); } // Add this move to dangerzone. diff --git a/ChessGame/MovementPatterns/KingPattern.cs b/ChessGame/MovementPatterns/KingPattern.cs index 1c599a8..6c916c4 100644 --- a/ChessGame/MovementPatterns/KingPattern.cs +++ b/ChessGame/MovementPatterns/KingPattern.cs @@ -25,11 +25,6 @@ public IEnumerable GetMoves(Piece piece, Coordinate position, Chessboard b continue; } - // whether the position is occupied. - Piece occupyingPiece = board.GetPiece(newPosition); - - TeamColor oppositeColor = piece.Color == TeamColor.Black ? TeamColor.White : TeamColor.Black; - // moved to before check dangersquare to possibly prevent weird king movement. if (guardedSquaresOnly) // return all protected squares { @@ -37,12 +32,17 @@ public IEnumerable GetMoves(Piece piece, Coordinate position, Chessboard b continue; } + TeamColor oppositeColor = piece.Color == TeamColor.Black ? TeamColor.White : TeamColor.Black; + // The king would put itself in check. if (board.IsDangerSquare(newPosition, oppositeColor) > 0) { continue; } + // whether the position is occupied. + Piece occupyingPiece = board.GetPiece(newPosition); + // is position empty? if (occupyingPiece is null) { From 294357b715b16ab5956adae5cb836ba8a078cb4d Mon Sep 17 00:00:00 2001 From: Kresten Laust Date: Fri, 27 Jan 2023 14:22:36 +0100 Subject: [PATCH 2/4] - Still doesn't pass tests - Fixed an issue with dangerzones not generating properly for pawns. It was because Pawns weren't unique, comparing pieces is now only a reference comparison --- ChessGame/Piece.cs | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/ChessGame/Piece.cs b/ChessGame/Piece.cs index 068b509..6300b2a 100644 --- a/ChessGame/Piece.cs +++ b/ChessGame/Piece.cs @@ -70,6 +70,7 @@ public IEnumerable GetMoves(Chessboard board, bool guardedSquaresOnly = fa public override string ToString() => Notation.ToString(); + /* public override bool Equals(object obj) { return obj is Piece piece && @@ -85,6 +86,6 @@ public override int GetHashCode() hashCode = hashCode * -1521134295 + Color.GetHashCode(); hashCode = hashCode * -1521134295 + MaterialValue.GetHashCode(); return hashCode; - } + }*/ } } From 4d87bf2ff88712114ab11c10d311b9d010e2badd Mon Sep 17 00:00:00 2001 From: Kresten Laust Date: Sat, 28 Jan 2023 15:04:08 +0100 Subject: [PATCH 3/4] Merge fix --- ChessCommandline/Program.cs | 6 +- ChessForms/BoardDisplay.cs | 387 +++++++++--------- ChessForms/PromotionPrompt.cs | 4 +- .../Properties/AssemblyInfo.cs | 1 - ChessGame.Bots/SimpletronBot.cs | 2 +- ChessGame.Bots/SkakinatorLogic.cs | 4 +- ChessGame.Bots/SkakinatorPlayer.cs | 1 - ChessGame.Tests/ClassicChessTest.cs | 7 +- ChessGame.Tests/DangerzoneTests.cs | 3 +- ChessGame/Chessboard.cs | 34 +- ChessGame/Gamemodes/CheckMateTest.cs | 4 +- ChessGame/Piece.cs | 33 +- 12 files changed, 238 insertions(+), 248 deletions(-) diff --git a/ChessCommandline/Program.cs b/ChessCommandline/Program.cs index 3d8ae25..9610e9f 100644 --- a/ChessCommandline/Program.cs +++ b/ChessCommandline/Program.cs @@ -1,8 +1,8 @@ -using ChessGame; +using System; +using System.Text; +using ChessGame; using ChessGame.Gamemodes; using ChessGame.Pieces; -using System; -using System.Text; namespace ChessCommandline; diff --git a/ChessForms/BoardDisplay.cs b/ChessForms/BoardDisplay.cs index 8b7488b..a669004 100644 --- a/ChessForms/BoardDisplay.cs +++ b/ChessForms/BoardDisplay.cs @@ -348,21 +348,18 @@ void ResetAllTableStyling() /// void DrawDangerzone() { - foreach (KeyValuePair> item in chessboard.Dangerzone) + foreach (KeyValuePair> item in chessboard.Dangerzone) { if (!chessboard.InsideBoard(item.Key)) { continue; } - if (item.Value.Count == 0) - { - continue; - } - - ColorSquare(item.Key, DangersquareColor); + if (item.Value.Count == 0) + { + continue; } - } + ColorSquare(item.Key, DangersquareColor); } } @@ -373,247 +370,247 @@ void DrawDangerzone() /// /// void MakeLocalMove(Coordinate from, Coordinate to) - { - IEnumerable moves = chessboard.GetMovesByNotation(from.ToString() + to.ToString(), chessboard.CurrentTeamTurn, MoveNotation.UCI); +{ + IEnumerable moves = chessboard.GetMovesByNotation(from.ToString() + to.ToString(), chessboard.CurrentTeamTurn, MoveNotation.UCI); - Move move = ChooseMove(moves); - if (move is null) - { - return; - } + Move move = ChooseMove(moves); + if (move is null) + { + return; + } - if (chessboard.PerformMove(move, false)) - { - recentMoveFrom = from; - recentMoveTo = to; + if (chessboard.PerformMove(move, false)) + { + recentMoveFrom = from; + recentMoveTo = to; - ResetAllTableStyling(); + ResetAllTableStyling(); - // Calls next worker. - backgroundWorkerMove.RunWorkerAsync(); - } + // Calls next worker. + backgroundWorkerMove.RunWorkerAsync(); } +} - Move ChooseMove(IEnumerable moves) - { - List pieces = new List(); +Move ChooseMove(IEnumerable moves) +{ + List pieces = new List(); - foreach (var move in moves) + foreach (var move in moves) + { + foreach (var singleMove in move.Submoves) { - foreach (var singleMove in move.Submoves) + if (singleMove.PromotePiece is null) { - if (singleMove.PromotePiece is null) - { - continue; - } - - pieces.Add(singleMove.PromotePiece); + continue; } - } - if (pieces.Count == 0) - { - return moves.FirstOrDefault(); + pieces.Add(singleMove.PromotePiece); } + } + + if (pieces.Count == 0) + { + return moves.FirstOrDefault(); + } - PromotionPrompt prompt = new PromotionPrompt(pieces); - DialogResult res = prompt.ShowDialog(); + PromotionPrompt prompt = new PromotionPrompt(pieces); + DialogResult res = prompt.ShowDialog(); - if (res == DialogResult.OK) + if (res == DialogResult.OK) + { + foreach (var move in moves) { - foreach (var move in moves) + foreach (var singleMove in move.Submoves) { - foreach (var singleMove in move.Submoves) + if (singleMove.PromotePiece.Notation == prompt.SelectedPiece.Notation) { - if (singleMove.PromotePiece.Notation == prompt.SelectedPiece.Notation) - { - return move; - } + return move; } } } - - return moves.First(); } - void CellClicked(object sender, EventArgs e) - { - MouseButtons button = ((MouseEventArgs)e).Button; + return moves.First(); +} - // translate window coordinates to table-cell coordinates - Point click = tableLayoutPanel1.PointToClient(MousePosition); - int windowX = click.X; - int windowY = click.Y; +void CellClicked(object sender, EventArgs e) +{ + MouseButtons button = ((MouseEventArgs)e).Button; - // TODO: Make grid accurate by making up for the difference the coordinate system makes. - int cellX = windowX / ((tableLayoutPanel1.Width - CoordinateSystemPixelSize) / chessboard.Width); - int cellY = windowY / ((tableLayoutPanel1.Height - CoordinateSystemPixelSize) / chessboard.Height); + // translate window coordinates to table-cell coordinates + Point click = tableLayoutPanel1.PointToClient(MousePosition); + int windowX = click.X; + int windowY = click.Y; - Coordinate clickTarget = new Coordinate(cellX, cellY); + // TODO: Make grid accurate by making up for the difference the coordinate system makes. + int cellX = windowX / ((tableLayoutPanel1.Width - CoordinateSystemPixelSize) / chessboard.Width); + int cellY = windowY / ((tableLayoutPanel1.Height - CoordinateSystemPixelSize) / chessboard.Height); - // handle click - switch (button) - { - // Deselects all squares marked, (de)selects a piece, or makes a move with a selected piece. - case MouseButtons.Left: - ResetAllTableStyling(); + Coordinate clickTarget = new Coordinate(cellX, cellY); - Piece piece = chessboard[clickTarget]; + // handle click + switch (button) + { + // Deselects all squares marked, (de)selects a piece, or makes a move with a selected piece. + case MouseButtons.Left: + ResetAllTableStyling(); + + Piece piece = chessboard[clickTarget]; + + // deselect piece selected + if (fromPosition is not null && piece?.Color == chessboard.CurrentTeamTurn && piece != selectedPiece) + { + DeselectPiece(fromPosition.Value.File, fromPosition.Value.Rank); + UpdateBoard(); + fromPosition = null; + } - // deselect piece selected - if (fromPosition is not null && piece?.Color == chessboard.CurrentTeamTurn && piece != selectedPiece) + if (fromPosition is null) + { + // return if piece is null or has wrong color. + if (piece?.Color != chessboard.CurrentTeamTurn) { - DeselectPiece(fromPosition.Value.File, fromPosition.Value.Rank); - UpdateBoard(); - fromPosition = null; + return; } - if (fromPosition is null) + // only allow selection of local players + if ((chessboard.CurrentTeamTurn == TeamColor.Black && !blackLocal) || + (chessboard.CurrentTeamTurn == TeamColor.White && !whiteLocal)) { - // return if piece is null or has wrong color. - if (piece?.Color != chessboard.CurrentTeamTurn) - { - return; - } + return; + } + + fromPosition = clickTarget; + SelectPiece(cellX, cellY); + selectedPiece = piece; - // only allow selection of local players - if ((chessboard.CurrentTeamTurn == TeamColor.Black && !blackLocal) || - (chessboard.CurrentTeamTurn == TeamColor.White && !whiteLocal)) + foreach (var move in piece.GetMoves(chessboard)) + { + if (move.Submoves[0].Destination is null) { - return; + continue; } - fromPosition = clickTarget; - SelectPiece(cellX, cellY); - selectedPiece = piece; + Coordinate guardedSquare = move.Submoves[0].Destination.Value; + + // TODO: Patrick fixer brættet, cirka her omkring + TilePictureControl cellImageControl = GetCell(guardedSquare.File, guardedSquare.Rank); + Image cellImage = cellImageControl.Image; + Color backgroundColor = cellImageControl.BackColor; - foreach (var move in piece.GetMoves(chessboard)) + bool isMoveValid = gamemode.ValidateMove(move, chessboard); + + if (move.Captures) { - if (move.Submoves[0].Destination is null) - { - continue; - } - - Coordinate guardedSquare = move.Submoves[0].Destination.Value; - - // TODO: Patrick fixer brættet, cirka her omkring - TilePictureControl cellImageControl = GetCell(guardedSquare.File, guardedSquare.Rank); - Image cellImage = cellImageControl.Image; - Color backgroundColor = cellImageControl.BackColor; - - bool isMoveValid = gamemode.ValidateMove(move, chessboard); - - if (move.Captures) - { - backgroundColor = isMoveValid ? - CaptureTileAvailableColor : - CaptureTileUnavailableColor; - } - else - { - cellImage = isMoveValid ? - Properties.Resources.MuligtTrkBrikTilgængelig : - Properties.Resources.MuligtTrkBrikUtilgængelig; - } - - cellImageControl.Image = cellImage; - cellImageControl.BackColor = backgroundColor; + backgroundColor = isMoveValid ? + CaptureTileAvailableColor : + CaptureTileUnavailableColor; } - } - else - { - // select target - if (clickTarget != fromPosition) + else { - MakeLocalMove(fromPosition.Value, clickTarget); + cellImage = isMoveValid ? + Properties.Resources.MuligtTrkBrikTilgængelig : + Properties.Resources.MuligtTrkBrikUtilgængelig; } - UpdateBoard(); - - DeselectPiece(cellX, cellY); - selectedPiece = null; - fromPosition = null; + cellImageControl.Image = cellImage; + cellImageControl.BackColor = backgroundColor; } - - break; - case MouseButtons.None: - break; - case MouseButtons.Right: // Mark square. - // do not change color if square is already colored. - if ((recentMoveFrom?.File == cellX && recentMoveFrom?.Rank == cellY) || - (recentMoveTo?.File == cellX && recentMoveTo?.Rank == cellY)) + } + else + { + // select target + if (clickTarget != fromPosition) { - break; + MakeLocalMove(fromPosition.Value, clickTarget); } - if (GetCell(cellX, cellY).BackColor == MarkedSquareColor) - { - ResetTileColor(cellX, cellY); - } - else - { - GetCell(cellX, cellY).BackColor = MarkedSquareColor; - } + UpdateBoard(); + DeselectPiece(cellX, cellY); + selectedPiece = null; + fromPosition = null; + } + + break; + case MouseButtons.None: + break; + case MouseButtons.Right: // Mark square. + // do not change color if square is already colored. + if ((recentMoveFrom?.File == cellX && recentMoveFrom?.Rank == cellY) || + (recentMoveTo?.File == cellX && recentMoveTo?.Rank == cellY)) + { break; - case MouseButtons.Middle: - break; - case MouseButtons.XButton1: - break; - case MouseButtons.XButton2: - break; - default: - break; - } - } + } - /// - /// Clears bordersrtle on a particular position. - /// - /// - /// - void DeselectPiece(int x, int y) - { - GetCell(x, y).BorderStyle = BorderStyle.None; - } + if (GetCell(cellX, cellY).BackColor == MarkedSquareColor) + { + ResetTileColor(cellX, cellY); + } + else + { + GetCell(cellX, cellY).BackColor = MarkedSquareColor; + } - /// - /// Changes borderstyle on a particular position. - /// - /// - /// - void SelectPiece(int x, int y) - { - GetCell(x, y).BorderStyle = BorderStyle.FixedSingle; + break; + case MouseButtons.Middle: + break; + case MouseButtons.XButton1: + break; + case MouseButtons.XButton2: + break; + default: + break; } +} - void BackgroundWorkerMove_DoWork(object sender, DoWorkEventArgs e) - { - chessboard.StartNextTurn(); - } +/// +/// Clears bordersrtle on a particular position. +/// +/// +/// +void DeselectPiece(int x, int y) +{ + GetCell(x, y).BorderStyle = BorderStyle.None; +} - void BackgroundWorkerMove_RunWorkerCompleted(object sender, RunWorkerCompletedEventArgs e) - { - } +/// +/// Changes borderstyle on a particular position. +/// +/// +/// +void SelectPiece(int x, int y) +{ + GetCell(x, y).BorderStyle = BorderStyle.FixedSingle; +} - void BoardDisplay_KeyUp(object sender, KeyEventArgs e) +void BackgroundWorkerMove_DoWork(object sender, DoWorkEventArgs e) +{ + chessboard.StartNextTurn(); +} + +void BackgroundWorkerMove_RunWorkerCompleted(object sender, RunWorkerCompletedEventArgs e) +{ +} + +void BoardDisplay_KeyUp(object sender, KeyEventArgs e) +{ + switch (e.KeyCode) { - switch (e.KeyCode) - { - case Keys.Left: - break; - case Keys.Right: - break; - case Keys.R: - // Refresh dangerzone - chessboard.UpdateDangerzones(); - break; - case Keys.Space: - // Display dangerzone - DrawDangerzone(); - break; - default: - break; - } + case Keys.Left: + break; + case Keys.Right: + break; + case Keys.R: + // Refresh dangerzone + chessboard.UpdateDangerzones(); + break; + case Keys.Space: + // Display dangerzone + DrawDangerzone(); + break; + default: + break; } } +} diff --git a/ChessForms/PromotionPrompt.cs b/ChessForms/PromotionPrompt.cs index 0f10198..d89d156 100644 --- a/ChessForms/PromotionPrompt.cs +++ b/ChessForms/PromotionPrompt.cs @@ -1,8 +1,8 @@ -using ChessGame; -using System; +using System; using System.Collections.Generic; using System.Drawing; using System.Windows.Forms; +using ChessGame; namespace ChessForms; diff --git a/ChessGame.Bots.Tests/Properties/AssemblyInfo.cs b/ChessGame.Bots.Tests/Properties/AssemblyInfo.cs index 50e9ae7..6bc9be2 100644 --- a/ChessGame.Bots.Tests/Properties/AssemblyInfo.cs +++ b/ChessGame.Bots.Tests/Properties/AssemblyInfo.cs @@ -1,5 +1,4 @@ using System.Reflection; -using System.Runtime.CompilerServices; using System.Runtime.InteropServices; [assembly: AssemblyTitle("ChessGame.Bots.Tests")] diff --git a/ChessGame.Bots/SimpletronBot.cs b/ChessGame.Bots/SimpletronBot.cs index 53227b0..20b4382 100644 --- a/ChessGame.Bots/SimpletronBot.cs +++ b/ChessGame.Bots/SimpletronBot.cs @@ -1,10 +1,10 @@ namespace ChessGame.Bots; +using ChessGame; using System.Collections.Concurrent; using System.Collections.Generic; using System.Linq; using System.Threading.Tasks; -using ChessGame; /// /// A very simple bot implementation. diff --git a/ChessGame.Bots/SkakinatorLogic.cs b/ChessGame.Bots/SkakinatorLogic.cs index 1dbf62b..d91df53 100644 --- a/ChessGame.Bots/SkakinatorLogic.cs +++ b/ChessGame.Bots/SkakinatorLogic.cs @@ -1,13 +1,13 @@ namespace ChessGame.Bots; +using ChessGame; +using ChessGame.Pieces; using System; using System.Collections.Concurrent; using System.Collections.Generic; using System.Linq; using System.Threading; using System.Threading.Tasks; -using ChessGame; -using ChessGame.Pieces; /// /// The logic of the Skakinator. diff --git a/ChessGame.Bots/SkakinatorPlayer.cs b/ChessGame.Bots/SkakinatorPlayer.cs index fb51b43..6f3f0a1 100644 --- a/ChessGame.Bots/SkakinatorPlayer.cs +++ b/ChessGame.Bots/SkakinatorPlayer.cs @@ -1,5 +1,4 @@ using System; -using ChessGame; namespace ChessGame.Bots; diff --git a/ChessGame.Tests/ClassicChessTest.cs b/ChessGame.Tests/ClassicChessTest.cs index 71eb89d..3b6977f 100644 --- a/ChessGame.Tests/ClassicChessTest.cs +++ b/ChessGame.Tests/ClassicChessTest.cs @@ -1,8 +1,5 @@ using ChessGame.Gamemodes; using ChessGame.Pieces; -using Microsoft.VisualStudio.TestTools.UnitTesting; -using System.Collections.Generic; -using System.Linq; namespace ChessGame.Tests; @@ -42,8 +39,8 @@ public void CheckPatternsTest() List moves = chessboard.GetMoves().ToList(); - // check if the amount of moves even is correct. - Assert.AreEqual(possibleMoves.Count, moves.Count); + // check if the amount of moves even is correct. + Assert.AreEqual(possibleMoves.Count, moves.Count); // checks if all moves are valid. foreach (var item in moves) diff --git a/ChessGame.Tests/DangerzoneTests.cs b/ChessGame.Tests/DangerzoneTests.cs index d54394a..99f9b90 100644 --- a/ChessGame.Tests/DangerzoneTests.cs +++ b/ChessGame.Tests/DangerzoneTests.cs @@ -1,5 +1,4 @@ -using System.Collections.Generic; -using ChessGame.Gamemodes; +using ChessGame.Gamemodes; using ChessGame.Pieces; namespace ChessGame.Tests; diff --git a/ChessGame/Chessboard.cs b/ChessGame/Chessboard.cs index bc1a21c..ca4c7e1 100644 --- a/ChessGame/Chessboard.cs +++ b/ChessGame/Chessboard.cs @@ -50,13 +50,13 @@ public Chessboard(Chessboard board) MovedPieces = new HashSet(board.MovedPieces); Moves = new Stack(board.Moves); - - Dangerzone = new Dictionary>(); - foreach (var item in board.Dangerzone) - { - Dangerzone[item.Key] = new HashSet(item.Value); - } + + Dangerzone = new Dictionary>(); + foreach (var item in board.Dangerzone) + { + Dangerzone[item.Key] = new HashSet(item.Value); } + } /// /// Initializes a new instance of the class, performs a deep-copy of the chessboard, and simulates a . @@ -75,11 +75,11 @@ public Chessboard(Chessboard board, Move move) MovedPieces = new HashSet(board.MovedPieces); Moves = new Stack(board.Moves.Reverse()); - Dangerzone = new Dictionary>(); - foreach (var item in board.Dangerzone) - { - Dangerzone[item.Key] = new HashSet(item.Value); - } + Dangerzone = new Dictionary>(); + foreach (var item in board.Dangerzone) + { + Dangerzone[item.Key] = new HashSet(item.Value); + } SimulateMove(move); } @@ -99,7 +99,7 @@ public Chessboard(byte width, byte height, Gamemode gamemode) CurrentState = GameState.NotStarted; Pieces = new Dictionary(); - Dangerzone = new Dictionary>(); + Dangerzone = new Dictionary>(); Moves = new Stack(); MovedPieces = new HashSet(); } @@ -112,7 +112,7 @@ public Chessboard(byte width, byte height, Gamemode gamemode) /// /// Gets a dictionary that describes intersection squares. An intersection square is a square which one or more pieces threaten at once. /// - public Dictionary> Dangerzone { get; } + public Dictionary> Dangerzone { get; } /// /// Gets previous moves, that resolve to this position. @@ -366,7 +366,7 @@ public bool IsKingInCheck(TeamColor color) } // Get list of pieces aiming on the square the king sits on. - if (Dangerzone.TryGetValue(position, out List pieces)) + if (Dangerzone.TryGetValue(position, out HashSet pieces)) { // Returns true if any of the pieces are of opposite teamColor. return pieces.Any(p => p.Color != color); @@ -533,7 +533,7 @@ public Move GetMoveByNotation(string notation, TeamColor teamColor, MoveNotation /// public int IsDangerSquare(Coordinate position, TeamColor teamColor) { - if (Dangerzone.TryGetValue(position, out List pieces)) + if (Dangerzone.TryGetValue(position, out HashSet pieces)) { return pieces is null ? 0 : pieces.Count(p => p.Color == teamColor); } @@ -548,7 +548,7 @@ public int IsDangerSquare(Coordinate position, TeamColor teamColor) /// public int GetDangerSquareSum(Coordinate position) { - if (!Dangerzone.TryGetValue(position, out List pieces)) + if (!Dangerzone.TryGetValue(position, out HashSet pieces)) { // No pieces can capture this tile. return 0; @@ -700,7 +700,7 @@ void UpdateDangerzones(Piece piece) // Make new list of pieces aiming on this square if there isn't one already. if (!Dangerzone.ContainsKey(destination)) { - Dangerzone[destination] = new List(); + Dangerzone[destination] = new HashSet(); } // Add this move to dangerzone. diff --git a/ChessGame/Gamemodes/CheckMateTest.cs b/ChessGame/Gamemodes/CheckMateTest.cs index 0d72edb..e828051 100644 --- a/ChessGame/Gamemodes/CheckMateTest.cs +++ b/ChessGame/Gamemodes/CheckMateTest.cs @@ -18,10 +18,10 @@ public override Chessboard GenerateBoard() { var board = new Chessboard(8, 8, this); - board[new Coordinate(0, 7-0)] = new King(TeamColor.White); + board[new Coordinate(0, 7 - 0)] = new King(TeamColor.White); board[new Coordinate(2, 2)] = new Pawn(TeamColor.White); board[new Coordinate(3, 2)] = new Pawn(TeamColor.White); - board[new Coordinate(4, 7-0)] = new King(TeamColor.Black); + board[new Coordinate(4, 7 - 0)] = new King(TeamColor.Black); board[new Coordinate(4, 5)] = new Pawn(TeamColor.Black); board[new Coordinate(5, 5)] = new Pawn(TeamColor.Black); /* diff --git a/ChessGame/Piece.cs b/ChessGame/Piece.cs index f4f58b5..17c831f 100644 --- a/ChessGame/Piece.cs +++ b/ChessGame/Piece.cs @@ -70,22 +70,21 @@ public IEnumerable GetMoves(Chessboard board, bool guardedSquaresOnly = fa public override string ToString() => Notation.ToString(); - /* - public override bool Equals(object obj) - { - return obj is Piece piece && - Notation == piece.Notation && - Color == piece.Color && - MaterialValue == piece.MaterialValue; - } - - public override int GetHashCode() - { - int hashCode = -1866919884; - hashCode = hashCode * -1521134295 + Notation.GetHashCode(); - hashCode = hashCode * -1521134295 + Color.GetHashCode(); - hashCode = hashCode * -1521134295 + MaterialValue.GetHashCode(); - return hashCode; - }*/ + /* + public override bool Equals(object obj) + { + return obj is Piece piece && + Notation == piece.Notation && + Color == piece.Color && + MaterialValue == piece.MaterialValue; } + + public override int GetHashCode() + { + int hashCode = -1866919884; + hashCode = hashCode * -1521134295 + Notation.GetHashCode(); + hashCode = hashCode * -1521134295 + Color.GetHashCode(); + hashCode = hashCode * -1521134295 + MaterialValue.GetHashCode(); + return hashCode; + }*/ } From 9c33a1c1f4132b572e932e0e1748c256b8f07020 Mon Sep 17 00:00:00 2001 From: Kresten Laust Date: Thu, 6 Jul 2023 20:40:27 +0200 Subject: [PATCH 4/4] Ran code cleanup --- ChessForms/BoardDisplay.cs | 360 +++++++++++++++--------------- ChessGame.Bots/SimpletronBot.cs | 2 +- ChessGame.Bots/SkakinatorLogic.cs | 4 +- 3 files changed, 183 insertions(+), 183 deletions(-) diff --git a/ChessForms/BoardDisplay.cs b/ChessForms/BoardDisplay.cs index c376e92..8f6964b 100644 --- a/ChessForms/BoardDisplay.cs +++ b/ChessForms/BoardDisplay.cs @@ -405,72 +405,72 @@ void DrawDangerzone() /// /// void MakeLocalMove(Coordinate from, Coordinate to) -{ - IEnumerable moves = chessboard.GetMovesByNotation(from.ToString() + to.ToString(), chessboard.CurrentTeamTurn, MoveNotation.UCI); - - Move move = ChooseMove(moves); - if (move is null) { - return; - } + IEnumerable moves = chessboard.GetMovesByNotation(from.ToString() + to.ToString(), chessboard.CurrentTeamTurn, MoveNotation.UCI); - if (chessboard.PerformMove(move, false)) - { - recentMoveFrom = from; - recentMoveTo = to; + Move move = ChooseMove(moves); + if (move is null) + { + return; + } - ResetAllTableStyling(); + if (chessboard.PerformMove(move, false)) + { + recentMoveFrom = from; + recentMoveTo = to; - // Calls next worker. - backgroundWorkerMove.RunWorkerAsync(); - } -} + ResetAllTableStyling(); -Move ChooseMove(IEnumerable moves) -{ - List pieces = new List(); + // Calls next worker. + backgroundWorkerMove.RunWorkerAsync(); + } + } - foreach (var move in moves) + Move ChooseMove(IEnumerable moves) { - foreach (var singleMove in move.Submoves) + List pieces = new List(); + + foreach (var move in moves) { - if (singleMove.PromotePiece is null) + foreach (var singleMove in move.Submoves) { - continue; - } + if (singleMove.PromotePiece is null) + { + continue; + } - pieces.Add(singleMove.PromotePiece); + pieces.Add(singleMove.PromotePiece); + } } - } - if (pieces.Count == 0) - { - return moves.FirstOrDefault(); - } + if (pieces.Count == 0) + { + return moves.FirstOrDefault(); + } - PromotionPrompt prompt = new PromotionPrompt(pieces); - DialogResult res = prompt.ShowDialog(); + PromotionPrompt prompt = new PromotionPrompt(pieces); + DialogResult res = prompt.ShowDialog(); - if (res == DialogResult.OK) - { - foreach (var move in moves) + if (res == DialogResult.OK) { - foreach (var singleMove in move.Submoves) + foreach (var move in moves) { - if (singleMove.PromotePiece.Notation == prompt.SelectedPiece.Notation) + foreach (var singleMove in move.Submoves) { - return move; + if (singleMove.PromotePiece.Notation == prompt.SelectedPiece.Notation) + { + return move; + } } } } - } - return moves.First(); -} + return moves.First(); + } -void CellClicked(object sender, EventArgs e) -{ - MouseButtons button = ((MouseEventArgs)e).Button; + void CellClicked(object sender, EventArgs e) + { + MouseButtons button = ((MouseEventArgs)e).Button; // translate window coordinates to table-cell coordinates Point click = tableLayoutPanelBoard.PointToClient(MousePosition); @@ -481,171 +481,171 @@ void CellClicked(object sender, EventArgs e) int cellX = windowX / ((tableLayoutPanelBoard.Width - CoordinateSystemPixelSize) / chessboard.Width); int cellY = windowY / ((tableLayoutPanelBoard.Height - CoordinateSystemPixelSize) / chessboard.Height); - Coordinate clickTarget = new Coordinate(cellX, cellY); + Coordinate clickTarget = new Coordinate(cellX, cellY); - // handle click - switch (button) - { - // Deselects all squares marked, (de)selects a piece, or makes a move with a selected piece. - case MouseButtons.Left: - ResetAllTableStyling(); - - Piece piece = chessboard[clickTarget]; - - // deselect piece selected - if (fromPosition is not null && piece?.Color == chessboard.CurrentTeamTurn && piece != selectedPiece) - { - DeselectPiece(fromPosition.Value.File, fromPosition.Value.Rank); - UpdateBoard(); - fromPosition = null; - } + // handle click + switch (button) + { + // Deselects all squares marked, (de)selects a piece, or makes a move with a selected piece. + case MouseButtons.Left: + ResetAllTableStyling(); - if (fromPosition is null) - { - // return if piece is null or has wrong color. - if (piece?.Color != chessboard.CurrentTeamTurn) - { - return; - } + Piece piece = chessboard[clickTarget]; - // only allow selection of local players - if ((chessboard.CurrentTeamTurn == TeamColor.Black && !blackLocal) || - (chessboard.CurrentTeamTurn == TeamColor.White && !whiteLocal)) + // deselect piece selected + if (fromPosition is not null && piece?.Color == chessboard.CurrentTeamTurn && piece != selectedPiece) { - return; + DeselectPiece(fromPosition.Value.File, fromPosition.Value.Rank); + UpdateBoard(); + fromPosition = null; } - fromPosition = clickTarget; - SelectPiece(cellX, cellY); - selectedPiece = piece; - - foreach (var move in piece.GetMoves(chessboard)) + if (fromPosition is null) { - if (move.Submoves[0].Destination is null) + // return if piece is null or has wrong color. + if (piece?.Color != chessboard.CurrentTeamTurn) { - continue; + return; } - Coordinate guardedSquare = move.Submoves[0].Destination.Value; - - // TODO: Patrick fixer brættet, cirka her omkring - TilePictureControl cellImageControl = GetCell(guardedSquare.File, guardedSquare.Rank); - Image cellImage = cellImageControl.Image; - Color backgroundColor = cellImageControl.BackColor; + // only allow selection of local players + if ((chessboard.CurrentTeamTurn == TeamColor.Black && !blackLocal) || + (chessboard.CurrentTeamTurn == TeamColor.White && !whiteLocal)) + { + return; + } - bool isMoveValid = gamemode.ValidateMove(move, chessboard); + fromPosition = clickTarget; + SelectPiece(cellX, cellY); + selectedPiece = piece; - if (move.Captures) + foreach (var move in piece.GetMoves(chessboard)) { - backgroundColor = isMoveValid ? - CaptureTileAvailableColor : - CaptureTileUnavailableColor; + if (move.Submoves[0].Destination is null) + { + continue; + } + + Coordinate guardedSquare = move.Submoves[0].Destination.Value; + + // TODO: Patrick fixer brættet, cirka her omkring + TilePictureControl cellImageControl = GetCell(guardedSquare.File, guardedSquare.Rank); + Image cellImage = cellImageControl.Image; + Color backgroundColor = cellImageControl.BackColor; + + bool isMoveValid = gamemode.ValidateMove(move, chessboard); + + if (move.Captures) + { + backgroundColor = isMoveValid ? + CaptureTileAvailableColor : + CaptureTileUnavailableColor; + } + else + { + cellImage = isMoveValid ? + Properties.Resources.MuligtTrkBrikTilgængelig : + Properties.Resources.MuligtTrkBrikUtilgængelig; + } + + cellImageControl.Image = cellImage; + cellImageControl.BackColor = backgroundColor; } - else + } + else + { + // select target + if (clickTarget != fromPosition) { - cellImage = isMoveValid ? - Properties.Resources.MuligtTrkBrikTilgængelig : - Properties.Resources.MuligtTrkBrikUtilgængelig; + MakeLocalMove(fromPosition.Value, clickTarget); } - cellImageControl.Image = cellImage; - cellImageControl.BackColor = backgroundColor; + UpdateBoard(); + + DeselectPiece(cellX, cellY); + selectedPiece = null; + fromPosition = null; } - } - else - { - // select target - if (clickTarget != fromPosition) + + break; + case MouseButtons.None: + break; + case MouseButtons.Right: // Mark square. + // do not change color if square is already colored. + if ((recentMoveFrom?.File == cellX && recentMoveFrom?.Rank == cellY) || + (recentMoveTo?.File == cellX && recentMoveTo?.Rank == cellY)) { - MakeLocalMove(fromPosition.Value, clickTarget); + break; } - UpdateBoard(); - - DeselectPiece(cellX, cellY); - selectedPiece = null; - fromPosition = null; - } + if (GetCell(cellX, cellY).BackColor == MarkedSquareColor) + { + ResetTileColor(cellX, cellY); + } + else + { + GetCell(cellX, cellY).BackColor = MarkedSquareColor; + } - break; - case MouseButtons.None: - break; - case MouseButtons.Right: // Mark square. - // do not change color if square is already colored. - if ((recentMoveFrom?.File == cellX && recentMoveFrom?.Rank == cellY) || - (recentMoveTo?.File == cellX && recentMoveTo?.Rank == cellY)) - { break; - } - - if (GetCell(cellX, cellY).BackColor == MarkedSquareColor) - { - ResetTileColor(cellX, cellY); - } - else - { - GetCell(cellX, cellY).BackColor = MarkedSquareColor; - } - - break; - case MouseButtons.Middle: - break; - case MouseButtons.XButton1: - break; - case MouseButtons.XButton2: - break; - default: - break; + case MouseButtons.Middle: + break; + case MouseButtons.XButton1: + break; + case MouseButtons.XButton2: + break; + default: + break; + } } -} -/// -/// Clears bordersrtle on a particular position. -/// -/// -/// -void DeselectPiece(int x, int y) -{ - GetCell(x, y).BorderStyle = BorderStyle.None; -} + /// + /// Clears bordersrtle on a particular position. + /// + /// + /// + void DeselectPiece(int x, int y) + { + GetCell(x, y).BorderStyle = BorderStyle.None; + } -/// -/// Changes borderstyle on a particular position. -/// -/// -/// -void SelectPiece(int x, int y) -{ - GetCell(x, y).BorderStyle = BorderStyle.FixedSingle; -} + /// + /// Changes borderstyle on a particular position. + /// + /// + /// + void SelectPiece(int x, int y) + { + GetCell(x, y).BorderStyle = BorderStyle.FixedSingle; + } -void BackgroundWorkerMove_DoWork(object sender, DoWorkEventArgs e) -{ - chessboard.StartNextTurn(); -} + void BackgroundWorkerMove_DoWork(object sender, DoWorkEventArgs e) + { + chessboard.StartNextTurn(); + } -void BackgroundWorkerMove_RunWorkerCompleted(object sender, RunWorkerCompletedEventArgs e) -{ -} + void BackgroundWorkerMove_RunWorkerCompleted(object sender, RunWorkerCompletedEventArgs e) + { + } -void BoardDisplay_KeyUp(object sender, KeyEventArgs e) -{ - switch (e.KeyCode) + void BoardDisplay_KeyUp(object sender, KeyEventArgs e) { - case Keys.Left: - break; - case Keys.Right: - break; - case Keys.R: - // Refresh dangerzone - chessboard.UpdateDangerzones(); - break; - case Keys.Space: - // Display dangerzone - DrawDangerzone(); - break; - default: - break; + switch (e.KeyCode) + { + case Keys.Left: + break; + case Keys.Right: + break; + case Keys.R: + // Refresh dangerzone + chessboard.UpdateDangerzones(); + break; + case Keys.Space: + // Display dangerzone + DrawDangerzone(); + break; + default: + break; + } } } -} diff --git a/ChessGame.Bots/SimpletronBot.cs b/ChessGame.Bots/SimpletronBot.cs index 20b4382..53227b0 100644 --- a/ChessGame.Bots/SimpletronBot.cs +++ b/ChessGame.Bots/SimpletronBot.cs @@ -1,10 +1,10 @@ namespace ChessGame.Bots; -using ChessGame; using System.Collections.Concurrent; using System.Collections.Generic; using System.Linq; using System.Threading.Tasks; +using ChessGame; /// /// A very simple bot implementation. diff --git a/ChessGame.Bots/SkakinatorLogic.cs b/ChessGame.Bots/SkakinatorLogic.cs index d91df53..1dbf62b 100644 --- a/ChessGame.Bots/SkakinatorLogic.cs +++ b/ChessGame.Bots/SkakinatorLogic.cs @@ -1,13 +1,13 @@ namespace ChessGame.Bots; -using ChessGame; -using ChessGame.Pieces; using System; using System.Collections.Concurrent; using System.Collections.Generic; using System.Linq; using System.Threading; using System.Threading.Tasks; +using ChessGame; +using ChessGame.Pieces; /// /// The logic of the Skakinator.