| 295 } |
295 } |
| 296 } |
296 } |
| 297 return false; |
297 return false; |
| 298 } |
298 } |
| 299 |
299 |
| |
300 static bool check_no_material_color(Color color, const GameState *gamestate) { |
| |
301 /* count the available pieces */ |
| |
302 unsigned piece_count[7] = {0}; |
| |
303 unsigned op_piece_count[7] = {0}; |
| |
304 bool has_bbishop = false, has_wbishop = false; |
| |
305 bool op_has_bbishop = false, op_has_wbishop = false; |
| |
306 for (Row r = 0 ; r < 8 ; r++) { |
| |
307 for (File f = 0 ; f < 8 ; f++) { |
| |
308 Piece p = piece_at(gamestate, r, f); |
| |
309 if (piece_color(p) == color) { |
| |
310 piece_count[piece_type(p)]++; |
| |
311 if (piece_type(p) == BISHOP) { |
| |
312 if (field_color(r, f) == WHITE) { |
| |
313 has_wbishop = true; |
| |
314 } else { |
| |
315 has_bbishop = true; |
| |
316 } |
| |
317 } |
| |
318 } else { |
| |
319 op_piece_count[piece_type(p)]++; |
| |
320 if (piece_type(p) == BISHOP) { |
| |
321 if (field_color(r, f) == WHITE) { |
| |
322 op_has_wbishop = true; |
| |
323 } else { |
| |
324 op_has_bbishop = true; |
| |
325 } |
| |
326 } |
| |
327 } |
| |
328 } |
| |
329 } |
| |
330 |
| |
331 /* rooks and queens are always enough - don't test them below */ |
| |
332 if (piece_count[ROOK] > 0 || piece_count[QUEEN] > 0) |
| |
333 return false; |
| |
334 |
| |
335 /* only the king left */ |
| |
336 if (piece_count[PAWN] == 0 && piece_count[KNIGHT] == 0 |
| |
337 && piece_count[BISHOP] == 0) |
| |
338 return true; |
| |
339 |
| |
340 /* king + knight and the opponent has only king + queens */ |
| |
341 if (piece_count[PAWN] == 0 && piece_count[BISHOP] == 0 |
| |
342 && piece_count[KNIGHT] == 1 |
| |
343 && op_piece_count[ROOK] == 0 && op_piece_count[BISHOP] == 0 |
| |
344 && op_piece_count[KNIGHT] == 0 && op_piece_count[PAWN] == 0 |
| |
345 && op_piece_count[QUEEN] > 0) |
| |
346 return true; |
| |
347 |
| |
348 /* king + bishop and the opponent doesn't have |
| |
349 * opposite color bishops or knights or pawns */ |
| |
350 if (piece_count[PAWN] == 0 && piece_count[KNIGHT] == 0 |
| |
351 && piece_count[BISHOP] > 0) { |
| |
352 |
| |
353 if (op_piece_count[KNIGHT] > 0 || op_piece_count[PAWN] > 0) |
| |
354 return false; |
| |
355 |
| |
356 if (has_bbishop && op_has_wbishop) |
| |
357 return false; |
| |
358 |
| |
359 if (has_wbishop && op_has_bbishop) |
| |
360 return false; |
| |
361 |
| |
362 return true; |
| |
363 } |
| |
364 |
| |
365 return false; |
| |
366 } |
| |
367 |
| |
368 bool check_no_material(const GameState *gamestate) { |
| |
369 return check_no_material_color(WHITE, gamestate) |
| |
370 && check_no_material_color(BLACK, gamestate); |
| |
371 } |
| |
372 |
| 300 char getpiecechr(Piece piece) { |
373 char getpiecechr(Piece piece) { |
| 301 switch (piece_type(piece)) { |
374 switch (piece_type(piece)) { |
| 302 case ROOK: return 'R'; |
375 case ROOK: return 'R'; |
| 303 case KNIGHT: return 'N'; |
376 case KNIGHT: return 'N'; |
| 304 case BISHOP: return 'B'; |
377 case BISHOP: return 'B'; |
| 415 apply_move_internal(gamestate, move); |
488 apply_move_internal(gamestate, move); |
| 416 |
489 |
| 417 /* calculate gamestate flags in order of efficiency */ |
490 /* calculate gamestate flags in order of efficiency */ |
| 418 if (move->checkmate) { |
491 if (move->checkmate) { |
| 419 gamestate->checkmate = true; |
492 gamestate->checkmate = true; |
| |
493 } else if (check_no_material(gamestate)) { |
| |
494 gamestate->nomaterial = true; |
| 420 } else if (check_threefold_repetition(gamestate)) { |
495 } else if (check_threefold_repetition(gamestate)) { |
| 421 gamestate->threefold = true; |
496 gamestate->threefold = true; |
| 422 } else if (check_stalemate(gamestate)) { |
497 } else if (check_stalemate(gamestate)) { |
| 423 gamestate->stalemate = true; |
498 gamestate->stalemate = true; |
| 424 } |
499 } |