X

Geertjan's Blog

  • August 24, 2005

Playing Chess with NetBeans IDE (Part 3)

Geertjan Wielenga
Product Manager
Now that web service support is available in Java applications, I've been making a lot of progress with the chess web service's client implementation. First, a picture -- this is what things look like right now (click to enlarge):

So, you make your move by adding a piece to the JLayeredPane.DRAG_LAYER and releasing it in a new square. Then (and this is the part that I'm still working on) you need a FEN string that represents the current state of the board, the active color, and the move number. (I'm temporarily using this FEN generator -- first I simulate the move in the FEN generator and then I copy the FEN string into the textfield at the bottom of my chess client.) When I click 'Send FEN', the FEN string is sent to the web service. (What's also sent is the search depth -- if your selected opponent is William Shakespeare, search depth is '5'. If your selected opponent is Alfred E. Neuman, search depth is '1'. In other words, this sets the difficulty level of the response move.)

When the web service returns (literally two or three seconds later, normally even less than that), all it gives you is the move (in the textfield at the top of the chess client), for example:

d7d5

This is all you get back from the web service. This is really great! Imagine, for example, if the web service returned another FEN string -- you'd have a lot of work to do to parse it and work out what to do with it. However, now that I know that the web service's response is 'd7d5', here's what I do -- for the start position -- to break it down into the letter part ('d') and the number part ('7'):

String move = myNorthField.getText();
String startposition_letter = move.substring(0,2);
int startposition_no = Integer.parseInt(move.substring(1,2));

(I do something similar for the end position, to attain the 'd' letter and the '5' number from 'd7d5'.)

So now I know the startposition letter for 'd7d5' is 'd' and the start position number is '7'. But how does the application know where this letter and position are found? It doesn't know that -- all it's done is attribute a number to a square. Here's the code that sets up the board:

public ChessBoard() {
Dimension boardSize = new Dimension(500, 500);
// Create a Layered Pane:
layeredPane = new JLayeredPane();
getContentPane().add(layeredPane);
layeredPane.setPreferredSize( boardSize );
layeredPane.addMouseListener( this );
layeredPane.addMouseMotionListener( this );
// Add a JPanel for the chessboard to the Layered Pane's default layer:
chessBoard = new JPanel();
layeredPane.add(chessBoard, JLayeredPane.DEFAULT_LAYER);
chessBoard.setLayout( new GridLayout(8, 8) );
chessBoard.setPreferredSize( boardSize );
chessBoard.setBounds(0, 0, boardSize.width, boardSize.height);
// Add a Jpanel for each square to the JPanel for the chessboard,
// white and black depending on calculation:
for (int i = 0; i < 64; i++) {
JPanel square = new JPanel( new BorderLayout() );
chessBoard.add( square );
int row = (i / 8) % 2;
if (row == 0)
square.setBackground( i % 2 == 0 ? Color.white : Color.black );
else
square.setBackground( i % 2 == 0 ? Color.black : Color.white );
}
}

So, from the application's perspective, this is what the board looks like:

However, since the web service sent you 'd7d5', this is how you'd like the application to see the board:

So, you need to convert the start position 'd7' to '11', which is d7's number on the board. Find 'd7' in the lower picture above and then find the number that represents that square in the upper picture: (i) in the upper picture, the lowest number in the column in which d7 is found is d7's column number, (ii) in the upper picture, the lowest number in the row in which d7 is found is d7's row number. In the upper picture, the lowest number in d7's column is 3. So, the column number is 3. In the upper picture, the lowest number in d7's row is 8. So, the row number is 8. So, 3 + 8 equals 11, which is the number on the board where 'd7' is found. Here's the code for all the columns:

if (startposition_letter.startsWith("a"))startpos_column_number = 0;
else if (startposition_letter.startsWith("b"))startpos_column_number = 1;
else if (startposition_letter.startsWith("c"))startpos_column_number = 2;
else if (startposition_letter.startsWith("d"))startpos_column_number = 3;
else if (startposition_letter.startsWith("e"))startpos_column_number = 4;
else if (startposition_letter.startsWith("f"))startpos_column_number = 5;
else if (startposition_letter.startsWith("g"))startpos_column_number = 6;
else if (startposition_letter.startsWith("h"))startpos_column_number = 7;

Notice how each startpos_column_number above (highlighted in the code above) matches the starting numbers of each column in the upper table. So, A is 0, B is 1, C is 2, etc.

And here's the code for all the rows:

if (startposition_no == 8)startpos_row_number = 0;
else if (startposition_no == 7)startpos_row_number = 8;
else if (startposition_no == 6)startpos_row_number = 16;
else if (startposition_no == 5)startpos_row_number = 24;
else if (startposition_no == 4)startpos_row_number = 32;
else if (startposition_no == 3)startpos_row_number = 40;
else if (startposition_no == 2)startpos_row_number = 48;
else if (startposition_no == 1)startpos_row_number = 56;

Notice how each startpos_row_number above (highlighted in the code above) matches the starting numbers of each row in the upper table. So, 8 is 0, 7 is 8, 6 is 16, etc.

The exact same procedure is then repeated for the end position (i.e., the 'd5' part of 'd7d5'). And then the piece is moved:

JPanel from = (JPanel)chessBoard.getComponent(startpos_column_number + startpos_row_number);
JLabel chessPiece = (JLabel)from.getComponent(0);
JPanel to = (JPanel)chessBoard.getComponent(endpos_column_number + endpos_row_number);
to.add(chessPiece);
from.revalidate();
to.revalidate();
layeredPane.repaint();

All of the above happens when the 'Send FEN' button is clicked. Of course, that button also invokes the actual call on the web service. But, as you can see from the complexity of translating the returned string to something that the application understands, the invocation on the web service is only one really small sub-step within a much larger whole. In other words, thanks to the Web Service Client wizard in NetBeans IDE Dev (which generates all the files and code snippets needed for communicating with the web service), contacting the web service is trivial. In many ways, the web service is nothing more than a glorified database -- because the IDE generates all the code for you, you might as well be using the Choose Database dialog box. And that's really quite wonderful.

The highlight of building this chess client, so far, was the moment when I clicked the 'Send FEN' button and -- two seconds later -- the black chess piece moved across the board by itself, using the string returned from the web service! That was pretty cool. So... now the next move in the building of my chess client is to generate that FEN string myself. Luckily I've been in touch with Valentin Iliescu, the creator of the chess web service and he's given me some really useful pointers.

Join the discussion

Comments ( 5 )
  • Alex Wednesday, August 24, 2005
    how is this system going to deal with moves like swapping castle with king, or pawn into queen after reaching opponent's baseline?
  • Anon Wednesday, August 24, 2005
    byte[] s = new String("d3d5").getBytes();
    int startpos_column_number = s[0] - 97;
    int startpos_row_number = (8 - (s[1] - 48)) \* 8;
    ...

    Sorry, i couldn't resist ;)

  • Geertjan Thursday, August 25, 2005
    Hi Alex and Anon! I haven't got far enough into the application yet to deal with castling and pawn promotion. I was actually thinking of skipping this altogether... but that's probably a bit of a cop out. Thanks Anon for providing a snippet of code to help me in that direction! The main thing I'm working on now is how to check whether the squares are empty or not (which is a necessary component of the FEN string that the web service needs to generate a response). Please do keep checking back here, my developments in this area will continue to be blogged about...
  • anon Friday, March 24, 2006
    The King and Queen are on the wrong squares in your diagram
  • guest Saturday, April 1, 2006
    good work
Please enter your name.Please provide a valid email address.Please enter a comment.CAPTCHA challenge response provided was incorrect. Please try again.