1.1 --- a/src/chess/rules.c Thu Apr 03 16:07:04 2014 +0200 1.2 +++ b/src/chess/rules.c Fri Apr 04 17:36:42 2014 +0200 1.3 @@ -90,12 +90,14 @@ 1.4 } 1.5 } 1.6 1.7 -_Bool is_covered(GameState *gamestate,uint8_t row,uint8_t file,uint8_t color) { 1.8 +_Bool get_any_threat_for(GameState *gamestate, uint8_t row, uint8_t file, 1.9 + uint8_t color, Move *threat) { 1.10 Move threats[16]; 1.11 int threatcount = 0; 1.12 for (uint8_t r = 0 ; r < 8 ; r++) { 1.13 for (uint8_t f = 0 ; f < 8 ; f++) { 1.14 if ((gamestate->board[r][f] & COLOR_MASK) == color) { 1.15 + memset(&(threats[threatcount]), 0, sizeof(Move)); 1.16 threats[threatcount].piece = gamestate->board[r][f]; 1.17 threats[threatcount].fromrow = r; 1.18 threats[threatcount].fromfile = f; 1.19 @@ -108,6 +110,9 @@ 1.20 1.21 for (int i = 0 ; i < threatcount ; i++) { 1.22 if (validate_move(gamestate, &(threats[i]))) { 1.23 + if (threat) { 1.24 + *threat = threats[i]; 1.25 + } 1.26 return 1; 1.27 } 1.28 } 1.29 @@ -158,7 +163,7 @@ 1.30 gamestate->board[move->torow][fileidx('d')] = color|ROOK; 1.31 } 1.32 } 1.33 - 1.34 + 1.35 addmove(gamestate, move); 1.36 } 1.37 1.38 @@ -179,8 +184,8 @@ 1.39 result = msrc(gamestate->board, move) == move->piece; 1.40 1.41 /* can't capture own pieces */ 1.42 - if ((mdst(gamestate->board, move) & COLOR_MASK) 1.43 - == (move->piece & COLOR_MASK)) { 1.44 + uint8_t piececolor = (move->piece & COLOR_MASK); 1.45 + if ((mdst(gamestate->board, move) & COLOR_MASK) == piececolor) { 1.46 return 0; 1.47 } 1.48 1.49 @@ -219,13 +224,70 @@ 1.50 return 0; 1.51 } 1.52 1.53 - /* is piece pinned */ 1.54 - // TODO: make it so 1.55 + /* find kings for check validation */ 1.56 + uint8_t mykingfile = 0, mykingrow = 0, opkingfile = 0, opkingrow = 0; 1.57 + for (uint8_t row = 0 ; row < 8 ; row++) { 1.58 + for (uint8_t file = 0 ; file < 8 ; file++) { 1.59 + if (gamestate->board[row][file] == 1.60 + (piececolor == WHITE?WKING:BKING)) { 1.61 + mykingfile = file; 1.62 + mykingrow = row; 1.63 + } else if (gamestate->board[row][file] == 1.64 + (piececolor == WHITE?BKING:WKING)) { 1.65 + opkingfile = file; 1.66 + opkingrow = row; 1.67 + } 1.68 + } 1.69 + } 1.70 + 1.71 + /* simulation move for check validation */ 1.72 + GameState simulation; 1.73 + memcpy(&simulation, gamestate, sizeof(GameState)); 1.74 + apply_move(&simulation, move); 1.75 + 1.76 + /* don't move into or stay in check position */ 1.77 + if (is_covered(&simulation, mykingrow, mykingfile, 1.78 + opponent_color(piececolor))) { 1.79 + return 0; 1.80 + } 1.81 1.82 /* correct check and checkmate flags (move is still valid) */ 1.83 - // TODO: make it so 1.84 + Move threat; 1.85 + move->check = get_any_threat_for(&simulation, opkingrow, opkingfile, 1.86 + piececolor, &threat); 1.87 1.88 - return result; 1.89 + if (move->check) { 1.90 + /* determine possible escape fields */ 1.91 + _Bool canescape = 0; 1.92 + for (int dr = -1 ; dr <= 1 && !canescape ; dr++) { 1.93 + for (int df = -1 ; df <= 1 && !canescape ; df++) { 1.94 + if (!(dr == 0 && df == 0) && 1.95 + isidx(opkingrow + dr) && isidx(opkingfile + df)) { 1.96 + 1.97 + /* escape field neither blocked nor covered */ 1.98 + if ((simulation.board[opkingrow + dr][opkingfile + df] 1.99 + & COLOR_MASK) != opponent_color(piececolor)) { 1.100 + canescape |= !is_covered(&simulation, 1.101 + opkingrow + dr, opkingfile + df, piececolor); 1.102 + } 1.103 + } 1.104 + } 1.105 + } 1.106 + /* can't escape, can we capture? */ 1.107 + if (!canescape) { 1.108 + canescape = is_covered(&simulation, threat.fromrow, 1.109 + threat.fromfile, opponent_color(piececolor)); 1.110 + 1.111 + /* can't capture, can we block? */ 1.112 + // TODO: make it so 1.113 + 1.114 + if (!canescape) { 1.115 + gamestate->checkmate = 1; 1.116 + } 1.117 + } 1.118 + } 1.119 + 1.120 + return 1; 1.121 } 1.122 1.123 int eval_move(GameState *gamestate, char *mstr, Move *move) {