Warning
Please, download this (corrected) version of ChessViewer
if you have downloaded it earlier (January 4). I am sorry, but that was an old, buggy version.
Introduction
One might argue the assertion, but I believe that any software developer must like chess. Portable Game Notation (PGN) is used to record chess games' moves and comments (e.g., 1. e4 e5 2. Nf3 ...). There are many chess PGN-viewers written in different languages and JavaScript is among them. But examples I stumbled upon were written using document.write
("Some HTML") operators. This style of programming looks awkward and does not arouse inspiration.
Background
They say that JavaScript supports object oriented style. To test this assertion, one may try to develop some "useful" application. When I realized the power of JavaScript and necessity to use it in modern web applications, I selected the problem of PGN-Viewer as a starting point. I mused the problem for several years and only now (in Christmas holidays), I found some time to implement the algorithm of calculating a FEN-like string
(describing a chess position after a current move) out of the previous FEN string
and current move notation.
FEN -- Forsyth–Edwards Notation (FEN). For instance, suppose that previous FEN-like string
is:
"rnb...nrpp.k.Bpp..pp................PB....bP.Q..P.PKN.PPq......R"
It describes all 64 squares of the chess board after 11-th move (see picture above). The next move is: 12. Nxc3 (knight captures a piece, black bishop, that occupies the field c3). The problem is to derive the next FEN-like string
after the move Nc3. This string
must look as:
"rnb...nrpp.k.Bpp..pp................PB....NP.Q..P.PK..PPq......R"
The problem does not seem very hard, but if you take into account that a move may have different formats depending on the current situation (Nc3
, Nec3
, N2c3
, Nxc3
, Nexc3
, N2xc3
, Nc3+
, Nec3+
, N2c3+
, Nxc3+
, Nexc3+
, N2xc3+
), then you would realize that there is something to do here. The greatest troubles are brought by the pawns' moves. You must consider: irregularity (pawn on e2
may go to e3
or e4
, but after that it may advance only by one square), en passant capture and possibility to transform to any piece (rank) on the last row. The last feature is called pawn promotion.
The best PGN-viewer I know (redhotpawn.com), uses predefined FEN strings for all the moves. I risk to make a mistake, but it seems as if they all were created by hand (huge efforts!).
Using the Code
You may use the script of this project to develop a web application that takes PGN-text from the user and gives him a possibility to watch the animation of any chess game, navigate through the moves, analyze the game and learn to play chess (the best game to develop one's mind). You also may add some of your favourite chess games texts to the existing list and use this application to spend a good time.
I plan to use this code in application that allows to play chess with my friends by the net. Yes, I know that this problem is solved, now anyone can play chess through the web, but using your own code (for the purpose of smoothly animating chess pieces) makes a difference. It is quite another story, the story that can arouse some inspiration.
Solution Structure
One of the most interesting things in this project is the MoverTimer
-- JavaScript object (prototype function) that allows you to simultaneously animate many images (pieces on the chess board). This happens when you select the arbitrary move from the list of moves at the right side of the control. If, say, 10 pieces must simultaneously travel to 10 different onboard positions, then 10 MoverTimer
objects must be created. Each must work separately and must not interfere the others. I found a wonderful example of a Timer at https://developer. mozilla.org and tweaked it slightly to correspond to my needs.
Second important detail is the AnimateTransition
-- method of PgnCtrl
object (JSON format is used). The algorithm of this method consists of 4 phases:
- Collect all the pieces on board.
- Go through all the squares, mark empty cells, pieces that are already in place, and pieces that need traveling (animating).
- Find the squares to move to, and mark the pieces that must travel to these squares. Create new pieces if needed.
- Go through all the pieces on board, calculate their new locations and start animating. Delete pieces that are not present in current FEN
string
.
Very convenient feature of MoverTimer
is the possibility to specify the callback function (with parameters) that will be called after the timer executes its task. I use this feature to call the Highlight
method that marks the move, controls the panel showing comments, and handles pawn's promotion.
When you analyze the move whose pgn is Qa8, you easily find the destination square (it is a8), but also you must find out (calculate) the source square (the square from which the queen is going to travel). This task is accomplished with a series of SearchXXX
methods of MoveAnalyzer
object, where XXX may be: North, West, South, East, NW, NE, SW or SE. Here, you can see the searching technique of a rook's source square.
SearchNESW: function (c)
{
if (!this.SearchNorth(c))
if (!this.SearchEast(c))
if (!this.SearchSouth(c))
if (!this.SearchWest(c))
return false;
return true;
}
The following scrap of code shows how to convert a destination square (e.g. 'e4
') to algebraic square coordinates used in the application.
ToX: function (c) { return c.charCodeAt(0) - 97; },
ToY: function (c) { return 8 - Number(c); },
Interesting is the fact that a king's and a knight's source position may be found using the same algorithm. That is because both pieces have 8 possible options. To find a pawn's previous position also presents a problem. All these tasks are handled with the SearchEight
, SearchPawn
and SearchEnPassant
methods of MoveAnalyzer
. To handle castlings (king and rook switching, O-O and O-O-O moves) proved to be much easier than it seemed.
Points of Interest
Try to load more than 2500 new games from the file Andersson.pgn (you will find it in the project folder). All of the newly loaded game notations will be added to the table supported by FileManager
object. Here, we use the functionality of JavaScript object named FileReader
. It is much more convenient than the formerly used MS COM object.
PgnCtrl
object creates UI elements. Here, certainly one could use some library (JQuery or better). One of my students showed me a library they use at the company, and it looked very powerful. Yes, some of our students work and study now (It was impossible before 1991 -- I wonder, is it good or not?). My deep conviction is that you should not use any library when learning a language. All the magic should be done with your own hands. That is why I use several global functions (you can find them in Kit.js). This small set of functions help to create all the UI.
I would like to conclude that JavaScript is great! Our evolution might have gone faster and, for sure, differently if its wide recognition had come earlier. I think during 10 years or more, only few people really saw the power of JavaScript and many of us simply neglected this wonderful dynamic language.