]> CyberLeo.Net >> Repos - FreeBSD/FreeBSD.git/blob - gnu/games/chess/Xchess/valid.c
This is the Linux generic soundcard driver, version 1.0c. Supports
[FreeBSD/FreeBSD.git] / gnu / games / chess / Xchess / valid.c
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