The trouble with knights….

In the continuing saga of making my own chess engine for Android, I’ve run into a peculiarity: If the king is in check, and the only move is a knight to capture the enemy to save the king, the app crashes. So, I added a try/catch block to the command to keep it from crashing. Then, instead of crashing, it would give me an error of the string being out of bounds. I placed the below log.i commands in to see the value of each character, so I could find the problem.

What I saw was that the king piece has no moves, so it was returning no moves at all. Odd, because if I insert a bishop to solve the problem, it would. The real issue still lies with the knight not reporting a valid move. Ironically, if I removed all other pieces, the knight can capture the enemy piece. Very, very odd….

[QUOTE]
public static void makeMove(String move) {
/*public static void makeMove(String move) {
int xf,yf,xt,yt;
//x1,y1,x2,y2,captured piece
if (move.charAt(4)!=’C’ && move.charAt(4)!=’P’) {
{
xt=Character.getNumericValue(move.charAt(2));
}
yt=Character.getNumericValue(move.charAt(3));
xf=Character.getNumericValue(move.charAt(0));
yf=Character.getNumericValue(move.charAt(1));
}
}*/
Log.i(“WJH”, String.valueOf(move.charAt(1)));
Log.i(“WJH”, String.valueOf(move.charAt(2)));
Log.i(“WJH”, String.valueOf(move.charAt(3)));
Log.i(“WJH”, String.valueOf(move.charAt(4)));

if (move.length() < 4) {
Log.i(“WJH”, “That piece cannot move.”);
} else {

if (move.charAt(4) != ‘P’) {
chessBoard[Character.getNumericValue(move.charAt(2))][Character.getNumericValue(move.charAt(3))] = chessBoard[Character.getNumericValue(move.charAt(0))][Character.getNumericValue(move.charAt(1))];
chessBoard[Character.getNumericValue(move.charAt(0))][Character.getNumericValue(move.charAt(1))] = ” “;
if (“K”.equals(chessBoard[Character.getNumericValue(move.charAt(2))][Character.getNumericValue(move.charAt(3))])) {
kingPositionC = 8 * Character.getNumericValue(move.charAt(2)) + Character.getNumericValue(move.charAt(3));
}
} else {
//if pawn promotion
chessBoard[1][Character.getNumericValue(move.charAt(0))] = ” “;
chessBoard[0][Character.getNumericValue(move.charAt(1))] = String.valueOf(move.charAt(3));
}
}
} // End makeMove
[/QUOTE]

Then, I decided to disable the kingsafe() check protocol, as seen here:
[QUOTE]
public static String posibleN(int i) {
String list=””, oldPiece;
int r=i/8, c=i%8;
for (int j=-1; j<=1; j+=2) {
for (int k=-1; k<=1; k+=2) {
try {
if (Character.isLowerCase(chessBoard[r+j][c+k*2].charAt(0)) || ” “.equals(chessBoard[r+j][c+k*2])) {
oldPiece=chessBoard[r+j][c+k*2];
chessBoard[r][c]=” “;
//if (kingSafe()) {
list=list+r+c+(r+j)+(c+k*2)+oldPiece;
//}
chessBoard[r][c]=”N”;
chessBoard[r+j][c+k*2]=oldPiece;
}
} catch (Exception e) {}
try {
if (Character.isLowerCase(chessBoard[r+j*2][c+k].charAt(0)) || ” “.equals(chessBoard[r+j*2][c+k])) {
oldPiece=chessBoard[r+j*2][c+k];
chessBoard[r][c]=” “;
//if (kingSafe()) {
list=list+r+c+(r+j*2)+(c+k)+oldPiece;
//}
chessBoard[r][c]=”N”;
chessBoard[r+j*2][c+k]=oldPiece;
}
} catch (Exception e) {}
}
}
return list;
} // End possible knight moves.
[/QUOTE]

By disabling kingsafe(), the knight was then able to move and capture the enemy piece that was threatening the king. Odd. Very odd. In the kingSafe() function, it is split for bishop/queen, and rook/queen, so I thought I would check to see if this is a bishop/queen problem, or a more general issue. Turns out it is not a specific bishop/queen attack problem, because a rook/queen attack also does not allow the knight to capture the attacker.

If I disable the kingSafe() check for the knight, then I proved the knight would move to capture a rook, only to open up an attack from a bishop. That obviously will not do. However, a very, very careful review of the rook’s code, versus the knight’s code revealed the mistake! See the code here:

[QUOTE]
++++++++++++++++++ KNIGHT +++++++++++++++++++++++++++
try {
if (Character.isLowerCase(chessBoard[r+j][c+k*2].charAt(0)) || ” “.equals(chessBoard[r+j][c+k*2])) {
oldPiece=chessBoard[r+j][c+k*2];
chessBoard[r][c]=” “;
//if (kingSafe()) {
list=list+r+c+(r+j)+(c+k*2)+oldPiece;
//}
chessBoard[r][c]=”N”;
chessBoard[r+j][c+k*2]=oldPiece;
}
}
++++++++++++++++++ ROOK ++++++++++++++++++++
if (Character.isLowerCase(chessBoard[r+temp*j][c].charAt(0))) {
oldPiece=chessBoard[r+temp*j][c];
chessBoard[r][c]=” “;
chessBoard[r+temp*j][c]=”R”;
if (kingSafe()) {
list=list+r+c+(r+temp*j)+c+oldPiece;
}
chessBoard[r][c]=”R”;
chessBoard[r+temp*j][c]=oldPiece;
}
[/QUOTE]

Notice that the rook “flow chart” as it were:
if the enemy is a bad guy, or blank, then {
write down what was there.
make the rook’s previous position empty.
place the rook in the new position.
NOW CHECK IF KING IS SAFE.
IF IT IS, MAKE THAT A PERMANENT MOVE.
IF NOT, PUT IT BACK.

Now look at the “flow chart for the knight:
if the enemy is a bad guy, or blank, then {
write down what was there.
make the knight’s previous position empty.

NOW CHECK IF KING IS SAFE.
IF IT IS, MAKE THAT A PERMANENT MOVE.
IF NOT, PUT IT BACK.

So, as you can see, the knight is not in the “new” position, thus the old piece is still there! With a quick re-write of that portion of code, then the knight worked as expected!

[QUOTE]
public static String posibleN(int i) {
String list=””, oldPiece;
int r=i/8, c=i%8;
for (int j=-1; j<=1; j+=2) {
for (int k=-1; k<=1; k+=2) {
try {
if (Character.isLowerCase(chessBoard[r+j][c+k*2].charAt(0)) || ” “.equals(chessBoard[r+j][c+k*2])) {
oldPiece=chessBoard[r+j][c+k*2];
chessBoard[r][c]=” “;
chessBoard[r+j][c+k*2]=”N”;
if (kingSafe()) {
list=list+r+c+(r+j)+(c+k*2)+oldPiece;
}
chessBoard[r][c]=”N”;
chessBoard[r+j][c+k*2]=oldPiece;
}
} catch (Exception e) {}
try {
if (Character.isLowerCase(chessBoard[r+j*2][c+k].charAt(0)) || ” “.equals(chessBoard[r+j*2][c+k])) {
oldPiece=chessBoard[r+j*2][c+k];
chessBoard[r][c]=” “;
chessBoard[r+j*2][c+k]=”N”;
if (kingSafe()) {
list=list+r+c+(r+j*2)+(c+k)+oldPiece;
}
chessBoard[r][c]=”N”;
chessBoard[r+j*2][c+k]=oldPiece;
}
} catch (Exception e) {}
}
}
return list;
} // End possible knight moves.
[/QUOTE]

Believe it or not, that was actually the most fun I have ever had programming in Java! Now I just have to solve the other ump-teen problems! Be sure to check out the commit here: https://github.com/alaskalinuxuser/apps_small/commit/0cd506f76578267c027b742e0de40fda392fd163.

Linux – keep it simple.

Leave a Reply

Your email address will not be published. Required fields are marked *