|
|
1.1 ! root 1: ! 2: /* This file contains code for X-CHESS. ! 3: Copyright (C) 1986 Free Software Foundation, Inc. ! 4: ! 5: This file is part of X-CHESS. ! 6: ! 7: X-CHESS is distributed in the hope that it will be useful, ! 8: but WITHOUT ANY WARRANTY. No author or distributor ! 9: accepts responsibility to anyone for the consequences of using it ! 10: or for whether it serves any particular purpose or works at all, ! 11: unless he says so in writing. Refer to the X-CHESS General Public ! 12: License for full details. ! 13: ! 14: Everyone is granted permission to copy, modify and redistribute ! 15: X-CHESS, but only under the conditions described in the ! 16: X-CHESS General Public License. A copy of this license is ! 17: supposed to have been given to you along with X-CHESS so you ! 18: can know your rights and responsibilities. It should be in a ! 19: file named COPYING. Among other things, the copyright notice ! 20: and this notice must be preserved on all copies. */ ! 21: ! 22: ! 23: /* RCS Info: $Revision: 1.3 $ on $Date: 86/11/23 17:18:35 $ ! 24: * $Source: /users/faustus/xchess/RCS/valid.c,v $ ! 25: * Copyright (c) 1986 Wayne A. Christopher, U. C. Berkeley CAD Group ! 26: * Permission is granted to do anything with this code except sell it ! 27: * or remove this message. ! 28: * ! 29: * Validate a move. ! 30: */ ! 31: ! 32: #include "xchess.h" ! 33: ! 34: extern bool ischeck(), couldmove(); ! 35: ! 36: bool ! 37: valid_move(m, b) ! 38: move *m; ! 39: board *b; ! 40: { ! 41: board tb; ! 42: ! 43: /* First check that the piece can make the move at all... */ ! 44: if (!couldmove(m, b)) ! 45: return (false); ! 46: ! 47: /* Now see if the king is in check now. */ ! 48: bcopy((char *) b, (char *) &tb, sizeof (board)); ! 49: board_move(&tb, m); ! 50: if (ischeck(&tb, m->piece.color)) ! 51: return (false); ! 52: ! 53: if (ischeck(&tb, ((m->piece.color == WHITE) ? BLACK : WHITE))) ! 54: m->check = true; ! 55: ! 56: return (true); ! 57: } ! 58: ! 59: static bool ! 60: couldmove(m, b) ! 61: move *m; ! 62: board *b; ! 63: { ! 64: int x, y; ! 65: ! 66: switch (m->type) { ! 67: case KCASTLE: ! 68: if ((m->piece.color == WHITE) && (b->white_cant_castle_k) || ! 69: (m->piece.color == BLACK) && ! 70: (b->black_cant_castle_k)) ! 71: return (false); ! 72: if ((b->square[m->fromy][5].color != NONE) || ! 73: (b->square[m->fromy][6].color != NONE)) ! 74: return (false); ! 75: if (ischeck(b, m->piece.color)) ! 76: return (false); ! 77: break; ! 78: ! 79: case QCASTLE: ! 80: if ((m->piece.color == WHITE) && (b->white_cant_castle_q) || ! 81: (m->piece.color == BLACK) && ! 82: (b->black_cant_castle_q)) ! 83: return (false); ! 84: if ((b->square[m->fromy][1].color != NONE) || ! 85: (b->square[m->fromy][2].color != NONE) || ! 86: (b->square[m->fromy][3].color != NONE)) ! 87: return (false); ! 88: if (ischeck(b, m->piece.color)) ! 89: return (false); ! 90: break; ! 91: ! 92: case MOVE: ! 93: case CAPTURE: ! 94: /* There is one special case here, that of taking a pawn ! 95: * en passant. In this case we change the move field to ! 96: * CAPTURE if it's ok. ! 97: */ ! 98: switch (m->piece.type) { ! 99: case PAWN: ! 100: if ((m->type == MOVE) && (m->fromx == m->tox)) { ! 101: /* A normal move. */ ! 102: if ((m->piece.color == WHITE) && (m->fromy == ! 103: m->toy + 1)) ! 104: break; ! 105: if ((m->piece.color == WHITE) && (m->fromy == ! 106: 6) && (m->toy == 4) && ! 107: (b->square[5][m->fromx].color ! 108: == NONE)) ! 109: break; ! 110: if ((m->piece.color == BLACK) && (m->fromy == ! 111: m->toy - 1)) ! 112: break; ! 113: if ((m->piece.color == BLACK) && (m->fromy == ! 114: 1) && (m->toy == 3) && ! 115: (b->square[2][m->fromx].color ! 116: == NONE)) ! 117: break; ! 118: return (false); ! 119: } else if (m->type == CAPTURE) { ! 120: if ((((m->piece.color == WHITE) && (m->fromy == ! 121: m->toy + 1)) || ((m->piece.color == ! 122: BLACK) && (m->fromy == m->toy - ! 123: 1))) && ((m->fromx == m->tox + 1) || ! 124: (m->fromx == m->tox - 1))) ! 125: break; ! 126: /* Now maybe it's enpassant... We've already ! 127: * checked for some of these things in the ! 128: * calling routine. ! 129: */ ! 130: if (m->enpassant) { ! 131: if (b->square[(m->piece.color == WHITE) ! 132: ? 3 : 4][m->tox].color == ! 133: ((m->piece.color == WHITE) ? ! 134: BLACK : WHITE)) ! 135: break; ! 136: } ! 137: return (false); ! 138: } ! 139: return (false); ! 140: ! 141: case ROOK: ! 142: if (m->fromx == m->tox) { ! 143: for (y = m->fromy + ((m->fromy > m->toy) ? -1 : ! 144: 1); y != m->toy; y += ((m->fromy ! 145: > m->toy) ? -1 : 1)) ! 146: if (b->square[y][m->tox].color != NONE) ! 147: return (false); ! 148: break; ! 149: } ! 150: if (m->fromy == m->toy) { ! 151: for (x = m->fromx + ((m->fromx > m->tox) ? -1 : ! 152: 1); x != m->tox; x += ((m->fromx ! 153: > m->tox) ? -1 : 1)) ! 154: if (b->square[m->toy][x].color != NONE) ! 155: return (false); ! 156: break; ! 157: } ! 158: return (false); ! 159: ! 160: case KNIGHT: ! 161: x = m->fromx - m->tox; ! 162: y = m->fromy - m->toy; ! 163: if ((((x == 2) || (x == -2)) && ! 164: ((y == 1) || (y == -1))) || ! 165: (((x == 1) || (x == -1)) && ! 166: ((y == 2) || (y == -2)))) ! 167: break; ! 168: return (false); ! 169: ! 170: case BISHOP: ! 171: x = m->fromx - m->tox; ! 172: y = m->fromy - m->toy; ! 173: if ((x != y) && (x != - y)) ! 174: return (false); ! 175: for (x = m->fromx + ((m->fromx > m->tox) ? -1 : 1), y = ! 176: m->fromy + ((m->fromy > m->toy) ? -1 : ! 177: 1); x != m->tox; ! 178: x += ((m->fromx > m->tox) ? -1 : 1), ! 179: y += ((m->fromy > m->toy) ? -1 : 1)) ! 180: if (b->square[y][x].color != NONE) ! 181: return (false); ! 182: break; ! 183: ! 184: case QUEEN: ! 185: if (m->fromx == m->tox) { ! 186: for (y = m->fromy + ((m->fromy > m->toy) ? -1 : ! 187: 1); y != m->toy; y += ((m->fromy ! 188: > m->toy) ? -1 : 1)) ! 189: if (b->square[y][m->tox].color != NONE) ! 190: return (false); ! 191: break; ! 192: } ! 193: if (m->fromy == m->toy) { ! 194: for (x = m->fromx + ((m->fromx > m->tox) ? -1 : ! 195: 1); x != m->tox; x += ((m->fromx ! 196: > m->tox) ? -1 : 1)) ! 197: if (b->square[m->toy][x].color != NONE) ! 198: return (false); ! 199: break; ! 200: } ! 201: x = m->fromx - m->tox; ! 202: y = m->fromy - m->toy; ! 203: if ((x != y) && (x != - y)) ! 204: return (false); ! 205: for (x = m->fromx + ((m->fromx > m->tox) ? -1 : 1), y = ! 206: m->fromy + ((m->fromy > m->toy) ? -1 : ! 207: 1); x != m->tox; ! 208: x += ((m->fromx > m->tox) ? -1 : 1), ! 209: y += ((m->fromy > m->toy) ? -1 : 1)) ! 210: if (b->square[y][x].color != NONE) ! 211: return (false); ! 212: break; ! 213: ! 214: case KING: ! 215: x = m->fromx - m->tox; ! 216: y = m->fromy - m->toy; ! 217: if ((x >= -1) && (x <= 1) && (y >= -1) && (y <= 1)) ! 218: break; ! 219: return (false); ! 220: } ! 221: break; ! 222: } ! 223: return (true); ! 224: } ! 225: ! 226: /* Say whether either king is in check... If move is non-NULL, say whether he ! 227: * in in check after the move takes place. We do this in a rather stupid way. ! 228: */ ! 229: ! 230: static bool ! 231: ischeck(b, col) ! 232: board *b; ! 233: color col; ! 234: { ! 235: int x, y, kx, ky; ! 236: move ch; ! 237: ! 238: for (x = 0; x < SIZE; x++) ! 239: for (y = 0; y < SIZE; y++) ! 240: if ((b->square[y][x].color == col) && ! 241: (b->square[y][x].type == KING)) { ! 242: kx = x; ! 243: ky = y; ! 244: } ! 245: ! 246: for (x = 0; x < SIZE; x++) ! 247: for (y = 0; y < SIZE; y++) ! 248: if (b->square[y][x].color == ((col == WHITE) ? ! 249: BLACK : WHITE)) { ! 250: ch.type = CAPTURE; ! 251: ch.piece.color = b->square[y][x].color; ! 252: ch.piece.type = b->square[y][x].type; ! 253: ch.fromx = x; ! 254: ch.fromy = y; ! 255: ch.tox = kx; ! 256: ch.toy = ky; ! 257: ch.enpassant = false; ! 258: if (couldmove(&ch, b)) ! 259: return (true); ! 260: } ! 261: ! 262: return (false); ! 263: } ! 264:
This archive runs on limited infrastructure. Preserving old code on modern bandwidth. Automated agents are requested to crawl responsibly.