If the applet is not visible above, you may need to install or upgrade your browser's plugin Java Runtime Engine (JRE). You may also need to change the Java advanced security settings in the Java control panel (accessible via the Windows Control Panel) to allow the user to grant permission to run. With the later versions of the JRE you may also have to add "http://rjwagner49.com" to the Exception Site List in the Security tab of the Java Control Panel (accessible from the Windows Control Panel). You may also need to check the "Do not check" button on "Perform signed code certificate revocation checks" in the Advanced tab of the Java control panel and possibly also in your browser advanced settings. Applets will run in Windows 10 with the Internet Explorer browser.
I named this computer chess applet a "homeostatic chess player" in honor of Philip K. Dick, the science fiction writer, who, in his stories, called his artificial intelligence (AI) devices "homeostatic." This online chess player is homeostatic in the sense that a well played chess game is a balance on the lines of strong moves in the chess game tree. By playing chess with this applet you are participating in an AI research experiment in distributed computation. Moves computed on your machine are sent to the chess memory server for storage and possible reuse. This is a good chess applet to play with for the following reasons:
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. 5.06 August 18, 2010: Recompiled to delete server features after the death of Hannes Mayer who graciously allowed the use of his SQL services. 6.03 November 24, 2012: Fixes a bug in the width of the message label. Now uses the Label function setMinimumSize() so that occasionally message text during computation isn't clipped. 7197 lines of code in the main file, chess.java. 6.05 May 18, 2016: Fixes a bug in which a checking pawn could not be captured en passant. 6.06 May 18, 2016: Adds requestFocus() to the mousemove event to allow reception of keystroke events. 6.08 December 29, 2019: More robust button panel and text label placement with the GridBagConstraints "insets" and "anchor."
Click the Extreme Tracker icon to see statistics for this page.
Email Richard dot J dot Wagner at gmail dot com
index.html, this hand crafted HTML file created February 15, 2001.
Last updated May 28, 2021, by
Dr. Rick Wagner. HTML code, chess applet, and Java source code copyright © 2001-2021, all rights reserved.