src/chess/rules.c

changeset 179
5ef724e21702
parent 177
18dbb0dc9cd6
equal deleted inserted replaced
178:724e8acff6f8 179:5ef724e21702
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 }

mercurial