src/chess/rules.c

changeset 28
0c1371488d87
parent 27
efeb98bc69c9
child 29
c6a1ad6cf749
     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) {

mercurial