The implementation of the chess rules
Until now we only wrote an interface a human can use to communicat with the programm. Now we start to write the artificial intelligense. As first step we teach our programm the chess rules.
We have to make a list with valid moves at two places: On one side to control the input of the human, on the other side to calculate the best move for the AI. We don't wan't to write everything twice, so implement the control of the moves of the human in such a way that we define an array in which we save all valid moves. The
isvalid ()method goes through the array and returns true if the move is in the list.To start we declare the variables we need:
//varibales for the AI
int [] movelist = new int [250];
int movecounter = 0;
int color = 1; //the color of the player that movesWe change the method
isvalid ():
//this method checks if a move is valid
public boolean isvalid (int move) {
for (int i = 0; i < movecounter; i++) {
if (movelist [i] == move)
return true;
}
return false;
}We also need the methods
simulize (),multisimulize ()andgenmove (). We start with the methodsimulize ():
//here we simulize a move
public void simulize (int start, int end) {
if ((board [end] == 99) ||
(board [end] % 100 / 10 == color))
return;
movelist [movecounter] = start * 100 + end;
movecounter++;
}The method checks first if the move crosses the border. If it does not, the move will be add to the movelist. Let's go to the multisimulize () methode. It simulizes the moves of the queen, bishop and rook.
//simulize the moves for queen, rook and bishop
public void multisimulize (int start, int inc) {
int to = start;
while ((board [to + inc ] != 99) && (board [to + inc] % 100 / 10 != color)) {
to += inc;
if (board [to] != 0) {
simulize (start, to);
return;
}
simulize (start, to);
}
simulize (start, to);
}This method gets the start field and the distance as parameter. Distance means the direction the piece moves to. Then the method simulizes moves until a barrier is in the way.
The most complicate method is
genmove (). Here the single moves are generated. You remember on the lines of the theory part in which we explained that every move can be expressed with a addition or subtracion? Now we implement that principe. Of course the numbers changes if you switch from a 8x8 board to a 12x10 board.
//This method generates all valid moves
public void genmove () {
for (int i = 21; i < 99; i++) {
//right color?
if (board [i] % 100 / 10 == color) {
switch (board [i] % 10) {
case 1: //pawn
if (color == 1) //white pawn
{
if (board [i-10] == 0)
simulize ( i, i-10);
if (board [i- 9] % 100 / 10 == 2)
simulize ( i, i-9 );
if (board [i-11] % 100 / 10 == 2)
simulize ( i, i-11);
if ( (i>80) && ( ( board [i-10] == 0) && (board [i-20] == 0)))
simulize ( i, i-20);
} else { //black pawn
if (board [i+10] == 0)
simulize ( i, i+10);
if (board [i+9] % 100 / 10 == 1)
simulize (i, i+9);
if (board [i+11] % 100 / 10 == 1)
simulize (i, i+11);
if ( (i<39) && ( (board [i+10] == 0) && (board [i+20] == 0)))
simulize (i, i+20);
}
break;
case 2: //knight
simulize (i, i+12);
simulize (i, i-12);
simulize (i, i+21);
simulize (i, i-21);
simulize (i, i+19);
simulize (i, i-19);
simulize (i, i+8 );
simulize (i, i-8 );
break;
case 5: //queen
case 3: //bishop
multisimulize ( i, -9);
multisimulize ( i, -11);
multisimulize ( i, +9);
multisimulize ( i, +11);
if (board [i] % 10 == 3)
break;
case 4: //rook
multisimulize (i, -10);
multisimulize (i, +10);
multisimulize (i, -1);
multisimulize (i, +1);
break;
case 6: //king
simulize (i, i+1);
simulize (i, i-1);
simulize (i, i+10);
simulize (i, i-10);
simulize (i, i+9);
simulize (i, i-9);
simulize (i, i+11);
simulize (i, i-11);
}
}
if ( i%10 == 8)
i += 2;
}
}We don't implement castling and en passant capturing. We will implement the castling in the part "final works", but we leave the en passant capturing because it isn't used really often. of course we have to call
genmove ()from anywhere. We call it in two methods:newgame ()andexecute (). So we add the following code at the end of the methodnewgame ():movecounter = 0;
color = 1;
genmove ();In the method
execute ()we have to change the move color so that white and black moves one after the other. The code looks out like this:
//other player
if (color == 1)
color = 2;
else
color = 1;
//set movelist back
movecounter = 0;
//calculate valid moves
genmove ();Now it should be clear why we use a 10x12 chess board, i.e. why we added a border. So it is much more easy to check if a move leads out of the regular board.
show applet step 5
source code of step 5