Click here to Skip to main content
65,938 articles
CodeProject is changing. Read more.
Articles / web / HTML

Chess PGN-Viewer (JavaScript)

4.85/5 (39 votes)
21 Jan 2015CPOL6 min read 68.7K   3K  
Object-oriented approach to Web Application developing using JavaScript

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.

Image 1

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.

License

This article, along with any associated source code and files, is licensed under The Code Project Open License (CPOL)