For more information about the operation of this client-server chess system, see our paper "A Distributed Model for Game Computing", which provides additional technical details. I hope you enjoy playing against the object oriented chess applet. It will average about one and a half minutes of thinking time per move. You can start a new browser session and let it run in the background while you work on other things, such as reading the rest of this page. It will "ding" when it has made its move (assuming your system supports sound).
One of the most rewarding things about writing this chess-playing applet is the large number of problems that had to be solved. This chess applet is written in Java using the Sun Java development kit (J2SE) so it will run on a wide variety of computers, including Apple Macintosh, Intel with Windows, OS/2, Linux, and many Unix machines.
Writing the program in Java provides portability among computers and operating systems. Writing it as an applet makes it easily distributed: anyone with an Internet connection and a Web browser can run (play) it. Writing it using the OO paradigm makes it easier to develop and maintain. The complete, fully operational, and tested applet took only about 100 hours to create (including design, coding, and testing). However, the Java language brings some performance issues to the programming problem. In fact, the chess applet runs 10 to 20 times slower than some chess programs written or compiled for specific hardware or operating systems. This results in the applet taking longer to look a certain number of moves ahead, or in looking fewer moves ahead for a given time. However, most people are not chess experts and will not mind having a slightly weaker computer opponent for recreational play.
The chess applet adapts its performance to your platform (hardware and runtime). If it moves in less than 30 seconds (averaged over the last two moves), on the next move it will look one half move further ahead. If it takes it longer than 200 seconds to move (a weighted average over the last four computer moves), on the next move it will look one half move less far ahead. If you find the playing strength of this applet to be too weak, it will be improved by running it on faster hardware.
There is a "computational wall" that AI programs tend to hit. Chess (and other games, such as go) belongs to this class of problems in computer science called "intractable," due to the "combinatorial explosion" of the branching of the chess game tree. The average branching factor of the chess game tree is about 34 for the whole game, and about 40 between 10 and 30 moves.
The fact of the computational difficulty of chess play underscores the remarkability of the achievement of IBM's Deep Blue chess computer which defeated the world's best human player, then world champion Garry Kasparov, in a fair match. That specialized machine could look ahead a full 12 moves (24 tempi). Shortly after Deep Blue's victory in 1997, I publicly predicted that it would never again lose a game to a human player under match conditions. To date, my prediction holds true. Deep Blue was subsequently disassembled and will likely never play again. Any future major effort at a chess computer is likely to be significantly more powerful than Deep Blue. Thus we may say that generally, humans are no longer better than computers at chess. The game of go, however, is even "more intractable" than chess, and it will be many years before computers will be able to beat the best human players at go.
I initially attempted to have a piece-centric (rather than board-centric) model, but was not able to get away from a chess board representation. With a piece-centric model, each piece will have knowledge of its location (or relationships to other pieces) and what its legal moves are. With a board-centric model, the board keeps the location of the pieces. My model has aspects of both in a way that I believe is optimal (for an OO approach).
The chess board is modeled as a 2D array of chess pieces. Empty squares have "null" for their pieces. Each piece has a "square" (rank and file) that it stands on and a list of squares it can move to in the next turn (a Vector of legal moves).
For the chess configuration space search algorithm, a tree node object is needed which has a configuration (chess board) and a chess board evaluation function. The game node keeps a Vector of child game nodes for recursive search (min-max with alpha-beta pruning). The game node object also has a "best" configuration to carry to the top of the tree when the search is complete. The applet itself also keeps a current board configuration. The applet also knows how to draw the chessboard and pieces and to interact with the user. To summarize, the following classes are defined:
The first heuristic is material value. A queen is more valuable than a knight, for example. My piece valuation system is based on traditional chess theory, with valuation as follows:
The material value heuristic takes precedence over positional subtleties. However, play is noticibly improved by adding a "freedom" heuristic: A position that has more legal moves available for one side than the other is better than one that does not. This heuristic is easy to implement by merely summing the legal moves available to each side and taking the difference. This heuristic encourages "freeing" moves in the opening, for example.
The third heuristic I implemented encourages moving each piece only once in the opening. Each piece is initially given a small penalty that is removed after it has been moved. "Piece" for this purpose does not include pawns, of course. Castling relieves the penalty doubly, and is thus encouraged.
Game tree search is depth first to a set depth that varies with computer performance. I used depth first search (rather than breadth first) so that child nodes could be destroyed before the full search is complete, saving memory.
Another search heuristic I implemented, that seems to improve play, is a truncated quiescense search. For any given move at the prescribed maximal search depth, if the move is a capture move, the algorithm will search one or two more levels, depending on whether the search depth is odd or even. The idea is that we want the final capture move to be by the player's opponent. An untruncated quiescence search was found to take too long. The current search depth is indicated in the Java console (from the "View" or "Window" menu of your browser).
A final heuristic is a small reward for advancing a pawn to help in the end game.
The position metric shown at the bottom of the board after each computer move is the future (look-ahead depth) board evaluation of the displayed position. A positive position metric is good for white.
Considering c5 (21) of 30 moves, 39 replies, 1852544 positions: Bc5 (0.47753)
This means that its option of moving a pawn to c5 is being considered, that it's the 21st of 30 moves to consider, that for this particular move, white has 39 replies, that so far it has looked at over 1.8 million board positions, and that moving its bishop to c5 is the best move found so far, with a position metric of 0.47753, which favors white. This message is updated every time it begins to evaluate another move. In this example, the message will be updated a total of 30 times before the computer makes its move.
Version 1.61 (March 28, 2001) indroduces a feature to disable the long sounds that play when checkmate occurs or when resetting the board. Clicking the "Disable Sound" button toggles the enabled state of the long sounds.
Test case two (g0000000002.txt) should work correctly with a search depth of four or more. Move the white knight to g6 and hit Control-C. The computer as black should save the king, not the rook.
Test case three (g0000000003.txt) should work correctly with a search depth of three or more. Hit Control-C and white should mate immediately.
Test case four (g0000000004.txt) should work correctly with a search depth of five or more. Hit Control-A and the white king should capture the pawn.
1.00 February 2, 2001: Development started, Chess.java file created, the board was drawn with character piece representations. Only pawn moves were under development in this first version. 1.38 February 26, 2001: all basic features operational for complete and correct chess play. The chess applet was Web published for testing on this day. 1.50 March 15, 2001: Sound feature added to the applet. 1.60 March 23, 2001: This version adds the game list text box feature. 1.61 March 27, 2001: This version adds the feature to disable the long playing sounds. 1.62 March 30, 2001: Adds the rank and file digits and letters to the chessboard. 1.65 May 23, 2001: Changes the elapsed time limits to 30 < e.t. < 600 s. Sets a minimum recursion depth to 3 half-moves, preventing a counter-check tactic. Also fixes a bug in interposing a piece in detection of checkmate by a queen. 1.67 February 14, 2002: Adds the move being considered to the message label when it's the computer's turn to move. 1.69 February 15, 2002: Allows the setting of the thinking time boundaries in the applet parameters. 1.70 February 17, 2002: Adds the number of the move being considered to the message label. 1.72 February 20, 2002: Implements testing for a draw by stalemate. 1.75 February 25, 2002: Implements testing for a draw by repetition and testing for a draw by lack of progress (no irreversible moves for 50 moves). Fixes a bug in checking for off-board moves in the generation of king moves. 1.76 February 26, 2002: Fixes a bug in the detection of a draw by repetition. 1.78 February 27, 2002: Fixes a bug in en passant capture by white. 1.80 February 27, 2002: Fixes a bug in the detection of a draw by stalemate. 1.82 March 1, 2002: Fixes a bug in the detection of checkmate and also fixes a bug that allowed a counter-checking tactic. 1.84 March 1, 2002: Simplifies the function checkmateP(). 1.85 March 4, 2002: Improves user messages in draw situations. 1.87 March 5, 2002: Fixes a bug added in versin 1.84 in the simplification of the checkmate detection function checkmateP(). 1.90 March 6, 2001: Fixes a bug in the detection of checkmate that would erroneously allow the capture by or interposition of a pinned piece. 1.93 March 7, 2002: Fixes a bug, found by Harald Schifferl, in the determination of the legal moves of a king. Improves search efficiency slightly by not considering the moves of knights pinned to kings. 2.00 March 8, 2002: Improves performance slightly by fixing a minor bug in the search depth computation and by removing some error trapping code. Removes some unused functions from the source code. Adjusts evaluation parameters slightly for stronger play in the opening. 2.08 March 12, 2002: Fixes a minor bug in refreshing legal moves. Improves performance slightly by not considering moves of bishops pinned to kings by rook mode nor moves of rooks pinned to kings by bishop mode. Disambiguates notation in the game listing when more than one of a piece type might make the move. 2.11 March 14, 2002: Fixes three minor bugs in generating the kings' moves: it would occasionally allow a king to check the other king, it would allow the king to capture a supported piece, and it inappropriately allowed kings' moves into check by pawns. 4874 lines of code, including comments and white space. 2.14 March 18, 2002: Reduces code size by loop rolling the generation of knight and king moves, making the source easier to maintain. 4463 lines of code. 2.24 March 27, 2002: Adds the save and load game features. 4751 lines of code and adds the two files ChessDataClient.java and ChessDataServer.java. 2.29 March 29, 2002: Allows the user to force the computer to make it's move with the control-M key combination. 4803 lines of code. 2.42 April 10, 2002: Adds the game file list feature for opening games. 4803 lines of code. 2.50 May 22, 2002: Fixes a rare bug in which the black king while in check under a mating attack might retreat to the square in line with the checking piece. 4877 lines of code. 2.56 June 11, 2002: Simplifies the computeMove() function and makes quiescence search depth a function of the general search depth for stronger play. 4962 lines of code. 2.61 June 14, 2002: Fixes a bug in setPiece() in which extra EP capture indications were generated. Results in slightly increased efficiency. 2.63 June 17, 2002: Implements computer resignation: the computer will resign if it sees a forced mate coming. 4900 lines of code. 2.69 June 29, 2002: Correctness first, then performance. Implements alpha-beta pruning for deeper thinking. 5083 lines of code. 2.82 July 10, 2002: Implements the auto-play feature, toggled on and off by control-A. Now the user can watch the computer play against itself. 5467 lines of code, including comments. 3.02 July 25, 2002: Implements chess server memory. In this version, the applet requests a position query and waits for the server callback. If the position is not found for the current or higher search depth, or if the server doesn't reply in five seconds, the applet computes the move and sends the result to the server for storage. 5964 lines of code, including comments. 3.12 August 8, 2002: Implements the control-R key combination for board rotation. 6196 lines of code, including comments. 3.18 August 6, 2002: Implements the control-I and control-D key combinations for board search depth incrementing and decrementing. 6248 lines of code, including comments. 3.22 August 23, 2002: Implements search depth boost computation based on hardware perforamance. The base six log of one over the test time duration is used to increment the default recursion limit. 6283 lines of code, including comments. 3.56 October 7, 2002: Adds the best move found so far to the "thinking" message. 4.00 October 31, 2002: Adds the chess piece color and contrast feature. 6575 lines of code. 4.07 November 6, 2002: Compiled with JDK v. 1.3.1. Compiled using the -O (optimize) switch for 10% more speed in move computation. Refines the alebraic notation function to more fully accord with convention. 4.17 February 18, 2003: Fixes a bug in disabling server memory use in duplicate positions. 4.21 June 10, 2003: Fixes a bug in dealing with pinned pieces. 4.22 December 16, 2003: Fixes another bug in dealing with pinned pieces. 4.26 January 29, 2004: Changes the client default socket port to 443 and adds code for setting the port with applet parameters. 4.27 March 22, 2004: Adds recursion limit incrementing in duplicate positions to try to avoid draws by repetition when the opponent is losing. Changes the default port back to 1997. 5.04 June 11, 2004: Changes chess memory and data service to MySQL server for hosting at chess.captain.at. Major upgrade by Hannes "Captain" Mayer, compiled for publication by Rick Wagner with JDK on Windows NT, in order to back off from the "bleeding edge." 5.05 September 16, 2004: Fixes a bug in the detection of pinned pieces. Thanks to Vleriy Diatchenko and Dr. Bob Hosken who both found the bug in the same week.
- The Automation and Robotics - Introductory Robotics Lectures for BCR Summer Camp
- The Computer Chess Programming page.
- Comprehensive chess links at RedWeb Chess.
- The United States Chess Federation.
- Play Mancala, the African board game.
- Rick's Chess Page.
- Ferguson Middle School Chess page.
- A General Order(n) Sort
- FixtureNet III
- Robotics Instruction Course
- Bill Johnson Landscape Photography
- Chess player Dr. Walter Wagner's World Botanical Gardens.
- Autobiography of Rick Wagner
- Strangelets: The Strange Matter of Planetary Destruction
- Captain's Ancient Coins site.
- Cosmic rays: a muon detector.
- Poetry by Annie Moses.
Click the Extreme Tracker icon to see statistics for this page.
This page created February 15, 2001.
Last updated: September 17, 2004 19:00:10 GMT
Your comments are welcome: RickWagner at ACM dot org.