|
|
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.