Changelog - SamChenYu/JavaChessEngine GitHub Wiki
04/03/24
Ok I have officially started working on the bitboard representation and it is a lot harder than I thought. There is a rabbit hole worth's of information about the move generation for bitboards. There are magic bitboards, lots of precomputing etc.
I was initially confused because I can easily generate the movement bitboards, but extracting the move information based off of that is hard. Therefore, I am going to loop through each piece and generate its movement / attack bitboards, then I will encode that into an integer of the form: [Type: 3 bits] [Start Square: 6 bits] [End Square: 6 bits] [Additional Data: variable]. There is a lot of bitwise operations that I am still getting used to. I have managed to begin writing up updating moves for the knight with bitwise operations.
I am still keeping some aspects of polymorphism within this new engine, however for the classes such as Piece and its children, they will all have static methods so there will be no instances of them because they are already included in the bitboards, but I will call their static methods to update so that the code is concise and not all under one class with tons of code.
28/02/24
Have been doing some research on bitboard move generation. Also I have completed further polymorphism by moving the isAttackingKing code to each individual piece.
23/02/24
Completed the polymorphism push by moving the piece square tables into the individual piece classes.
22/02/24
Added more functionality so that depth can be adjusted in the GUI. I have also started refactoring and adding more polymorphism into the Move class and classifying each type of move into a separate child class. Now that I have fully integrated this, the engine class has considerably a lot less switch statements which accelerates the processing speed. I used a midgame FEN position to test the difference between the versions 3 times, where every piece was developed and had equal material. On average, the earlier version took an average of 11.4 minutes for 2,159,898 moves whilst the updated version took an average of 3.2 minutes for the same amount of moves. This is a very good increase in speed, and even faster in the opening / endgame. FEN used for testing: r1b1k2r/pp2bppp/2n1p3/qBppPn2/P2P1B2/2P2N2/1P3PPP/RN1QR1K1 w kq - 0 1
21/02/24
I have updated the 2D piece representation... I realised I had a lot of inefficiencies that could have been solved with polymorphism. I created child classes of Piece for all piece types. I can also do this to create child class of Move too. The bitboard development had been paused for a bit.
16/02/24
Started looking at optimizing the entire program. I have created a separate branch on the repository where I'll store the old code containing the Piece[][] 2D array representation. I am now working on implementing bitboards, which should improve efficiency greatly. I will have to rework the entire engine as the accessing will be different.
10/02/24
Changed the minimax algorithm to add in top 2 and 3 moves, then changed the GUI to reflect this. I also refactored code and split the engine code into a MoveGenerator class, so that it divides up the code from 3000 lines to 1000 lines in the engine instead, which makes it a lot cleaner. I also added more interactivity, where the user can now play moves directly on the panel. This was implemented by 64 invisible JButtons - as opposed to hidden rectangles as I didn't want a thread constantly checking mouse clicks and coordinates.
08/02/24
Brushed up the GUI by implementing dependency injection between the enginepanel and engine such that all the data on the GUI can be updated. Fixed up so that the moves are playable on the screen. However, there are some issues. For some reason, black is generating their worst move. I fixed this because the black player was maximising for the white player.
04/02/24
OK I realised that I had done something very wrong. I had a bug where the colors wouldn't swap properly. and when you reverted moves, all the black moves reverted to white in the minimax algorithm,. I fixed this and the performance is a lot faster now. Depth 4 from previous 256,123 states, 198 seconds to 206,605 states in 4.3 seconds!! HOLY SHIT I PLAYED IT AGAINST MARTIN AGAIN AND IT WON. IT SAW MOVES THAT I DIDN'T REALLY THINK OF. IT GOT A RATING OF 1150 ESTIMATE FROM THE ANALYSIS AND THIS IS JUST DEPTH 4. To be honest the game took around an hour to play because it's not very efficient ~ it takes around 3-5 minutes to calculate moves. Other things to take note of is that it missed checkmate in 1 so that probably needs to be tweaked.
03/02/24
Updated the evaluation function - with dynamic weighting. So far I am factoring position and material. However based on the amount of material lost, the weighting will be different. For similar material, the position will be weighted more. For vast material difference, the material difference will be factored more. I have used a sigmoid function to get the evaluation for material difference, since 1 point difference is quite minute, however 3 points is losing. Anything above 9-39 points is going to be extremely losing. I fixed the issues of having only one arraylist in the entire program, to allocating new ones for future moves. I brushed up on some other stuff and now the entire program works with no runtime errors! However there are some bugs because some moves aren't being reverted back in the correct color. There are some issues for when the colors are flipped. Some figures: Depth 4: 255,123 games searched, 198 seconds: pawn e2 to e4 (very good!!) Depth 3: 4882 games searched, 3 seconds Depth 2: 461 games searched, 0.033 seconds Depth 1: 21 games searched, 0.007 seconds
01/02/24
There are certain issues that I need to fix now. The game object has an arraylist of moves that it can perform. Therefore within the minimax algorithm, it will wipe it and update when a new move is called. This means that the old moves have been removed, and it will be impossible to revert. I need to make the moves list independent of the game object. Also I am improving the evaluation method by adding material a factor, but I am trying to balance out the weightage.
31/01/24
MiniMax algorithm was setup, but not tested completely. I also added Piece Square Tables from sources online. The chess engine played its first match against Martin (250 elo) on chess.com at depth 1. It played terribly and lost in 48 moves. It had an overall accuracy of 66.4 % and was rated 100 elo. This is because it only took in the piece square tables which are good for developing the pieces, but has no logic in capturing.
28/01/24
Calculate possible moves function completely overhauled. Instead of copying a game thousands of times, it had the ability to make the move, and then revert the move back to the original state which had a lot more code complexity, but I was able to keep the time effiency to about 0.01 seconds, which is so much faster than before. The two functions makeMove and revertMove took a lot of complexity as you have to save certain states of the game and restore them.
18/01/24
isCheckMateFunction created. MakeMove function was created. At this stage it had to create a copy of the board (since it was java, all the references were pointers and not values so the board had to be copied all 64 squares including castling rights, etc) and then it would check if you are in check. If you were in check, it would not be a valid move. If there are no legal moves and you are in check, then it is checkmate At this point it would take about ~0.734 seconds to generate a legal moves list. In terms of chess engine efficiency, this is terrible.
14/01/24
Calculate Possible Moves Function created. Loops through 64 squares and updates which pieces can move or not. Currently did not handle pins or whether king was in check
10/01/24
GUI created. Control Panel to create enginepanels which displayed the board
08/01/24 Basic evaluation function. Loops through 64 squares and adds up material. Evaluation only counts material loss and gain
07/01/24
Beginning of project. Researched about FEN notation and realised that a chess game has a lot more states than just the board: King Castling Rights for each side, color and En Passant Produced String handling to input the FEN notation The way the board is setup is in a 2D array of Piece objects [0][0] correlates to A1 [7][7] correlates to H7
However, if you try to print it out like this: for(int i=0; i<8; i++) { for(int j=0; i<8;j++) { System.out.println(board[i][j].getPieceName()); } }
It will print out sideways as you are looping through FILES (Column) instead of the RANKS (Row) This confused me quite a bit during development.