10 // define MAXDEPTH = 6;
11 define MAXDEPTH_PASS2 = 50;
13 static MoveStack moveStack[MAXDEPTH_PASS2];
15 void AddMoveToList(MoveStack stack, ChessState state, PieceType type, Player player,
16 int x1, int y1, int x2, int y2)
18 if(IsMoveValid(x1,y1,x2,y2, state, null, true))
22 if(stack.count + 1 > stack.size)
25 stack.moves = renew stack.moves ChessMove[stack.size];
28 move = &stack.moves[stack.count++];
30 move->player = player;
36 // For now queen only...
37 move->promotion = Queen;
41 void GeneratePieceMoveList(ChessState state, int x, int y, MoveStack stack)
43 Piece content = state.board[y][x];
44 Player player = content.player;
45 PieceType type = content.type;
52 int direction = (player == White) ? 1 : -1;
54 AddMoveToList(stack, state, type, player, x,y,x,y+direction);
56 if((player == White && y == 1) ||
57 (player == Black && y == 6))
58 AddMoveToList(stack, state, type, player, x,y,x,y+direction*2);
60 // Capturing Move (Including en passant)
62 AddMoveToList(stack, state, type, player, x,y,x-1,y+direction);
64 AddMoveToList(stack, state, type, player, x,y,x+1,y+direction);
68 AddMoveToList(stack, state, type, player, x,y, x+1,y+2);
69 AddMoveToList(stack, state, type, player, x,y, x+2,y+1);
70 AddMoveToList(stack, state, type, player, x,y, x+2,y-1);
71 AddMoveToList(stack, state, type, player, x,y, x+1,y-2);
72 AddMoveToList(stack, state, type, player, x,y, x-1,y-2);
73 AddMoveToList(stack, state, type, player, x,y, x-2,y-1);
74 AddMoveToList(stack, state, type, player, x,y, x-2,y+1);
75 AddMoveToList(stack, state, type, player, x,y, x-1,y+2);
79 for(x2 = 0; x2<8; x2++)
85 AddMoveToList(stack, state, type, player, x,y,x2,y2);
88 AddMoveToList(stack, state, type, player, x,y,x2,y2);
94 for(x2 = 0; x2<8; x2++)
98 AddMoveToList(stack, state, type, player, x,y,x2,y);
101 for(y2 = 0; y2<8; y2++)
105 AddMoveToList(stack, state, type, player, x,y,x,y2);
110 for(x2 = 0; x2<8; x2++)
114 y2 = y + Abs(x2 - x);
116 AddMoveToList(stack, state, type, player, x,y,x2,y2);
117 y2 = y - Abs(x2 - x);
119 AddMoveToList(stack, state, type, player, x,y,x2,y2);
122 for(x2 = 0; x2<8; x2++)
126 AddMoveToList(stack, state, type, player, x,y,x2,y);
129 for(y2 = 0; y2<8; y2++)
133 AddMoveToList(stack, state, type, player, x,y,x,y2);
138 AddMoveToList(stack, state, type, player, x,y, x,y+1);
139 AddMoveToList(stack, state, type, player, x,y, x+1,y+1);
140 AddMoveToList(stack, state, type, player, x,y, x+1,y);
141 AddMoveToList(stack, state, type, player, x,y, x+1,y-1);
142 AddMoveToList(stack, state, type, player, x,y, x,y-1);
143 AddMoveToList(stack, state, type, player, x,y, x-1,y-1);
144 AddMoveToList(stack, state, type, player, x,y, x-1,y);
145 AddMoveToList(stack, state, type, player, x,y, x-1,y+1);
148 AddMoveToList(stack, state, type, player, x,y, x-2,y);
149 AddMoveToList(stack, state, type, player, x,y, x+2,y);
154 void GenerateMoveList(ChessState state, MoveStack stack)
162 Piece content = state.board[y][x];
163 if(content && content.player == state.turn)
164 GeneratePieceMoveList(state, x,y, stack);
168 int EvaluateMaterial(Piece board[8][8], Player turn)
171 int materialMe = 0, materialOpp = 0;
176 Piece content = board[y][x];
177 if(content != Piece {})
179 Player player = content.player;
180 PieceType piece = content.type;
183 materialMe += materialValues[piece];
185 materialOpp += materialValues[piece];
188 return materialMe - materialOpp;
191 int EvaluatePosition(ChessState state, Player turn)
195 // To help the mate...
196 if(state.materialValue[White] < 7)
198 if((state.kings[White].x >= 3 && state.kings[White].x <= 4) &&
199 (state.kings[White].y >= 3 && state.kings[White].y <= 4))
203 else if((state.kings[White].x >= 2 && state.kings[White].x <= 5) &&
204 (state.kings[White].y >= 2 && state.kings[White].y <= 5))
208 else if((state.kings[White].x >= 1 && state.kings[White].x <= 6) &&
209 (state.kings[White].y >= 1 && state.kings[White].y <= 6))
216 if(state.castled[White]) position -= 15;
217 if(state.castled[Black]) position += 15;
221 static int CompareGreater(const ChessMove a, const ChessMove b)
223 if(a.rating > b.rating) return 1;
224 else if(a.rating < b.rating) return -1;
227 if(a.count < b.count) return 1;
228 else if(a.count > b.count) return -1;
234 static int CompareSmaller(const ChessMove a, const ChessMove b)
236 if(a.rating < b.rating) return 1;
237 else if(a.rating > b.rating) return -1;
240 if(a.count > b.count) return 1;
241 else if(a.count < b.count) return -1;
247 bool FindMove(ChessState startState, int depth, int *maxDepth, ChessMove bestMove, int startRating, int * returnedRating,
248 int startCount, int * returnedCount, bool * abort)
250 Player player = startState.turn;
251 MoveStack * stack = &moveStack[depth];
252 int bestRating = (player == Black) ? MININT : 200000;
254 int bestCount = MAXINT;
255 int maxShots = stack->count;
258 if(*abort) return false;
260 GenerateMoveList(startState, stack);
261 if(!stack->count && !Check(startState, player, startState.kings[player].x, startState.kings[player].y))
265 bestCount = startCount;
267 maxShots = stack->count;
268 for(c = 0; c<maxShots; c++)
270 ChessMove * move = &stack->moves[c];
271 int newRating, newCount = MAXINT;
273 ChessState state = startState;
275 StateMakeMove(&state, move->x1, move->y1, move->x2, move->y2, move->promotion, false, &delta);
279 if(Abs(delta) < 1000 && (depth+1 < *maxDepth))
281 FindMove(&state, depth+1, maxDepth, null, startRating + delta, &newRating, startCount+1, &newCount, abort);
286 position = EvaluatePosition(&state, player);
287 newRating = startRating + delta + position;
289 if((player == Black) ? (newRating > bestRating) : (newRating < bestRating))
290 newCount = startCount+1;
293 move->rating = newRating;
294 move->count = newCount;
296 if((player == Black) ? (newRating >= bestRating) : (newRating <= bestRating))
298 bestRating = newRating;
299 if(move->count < bestCount)
300 bestCount = move->count;
303 stack->count = maxShots;
306 if(bestMove && stack->count)
310 qsort(stack->moves, stack->count, sizeof(ChessMove), CompareSmaller);
312 qsort(stack->moves, stack->count, sizeof(ChessMove), CompareGreater);
314 for(numGoodMoves = 0; numGoodMoves<stack->count; numGoodMoves++)
316 if(stack->moves[numGoodMoves].rating != bestRating)
318 if(stack->moves[numGoodMoves].count != bestCount)
322 c = GetRandom(0, numGoodMoves-1);
323 bestMove = stack->moves[c];
326 *returnedRating = bestRating;
328 *returnedCount = bestCount;
331 return stack->count > 0;
334 class AIThread : Thread
350 chess.MakeMove(aiMove.x1, aiMove.y1, aiMove.x2, aiMove.y2, aiMove.promotion);
351 aiMoveResult = false;
371 aiMoveResult = false;
374 ChessState * chessState;
378 ChessState * chessState = chess.chessState;
379 int startRating = EvaluateMaterial(chessState->board, chessState->turn);
380 int depth = MAXDEPTH;
382 RandomSeed((uint)(((uint64)(GetTime() * 1000)) & MAXDWORD));
383 aiMoveResult = FindMove(chessState, 0, &depth, &aiMove, startRating, null, 0, null, &abortAI);
389 property Chess chess { set { chess = value; } }
390 property ChessState * chessState { set { chessState = value; } }