|
|
1.1 root 1: /* This file contains code for X-CHESS.
2: Copyright (C) 1986 Free Software Foundation, Inc.
3:
4: This file is part of X-CHESS.
5:
6: X-CHESS is distributed in the hope that it will be useful,
7: but WITHOUT ANY WARRANTY. No author or distributor
8: accepts responsibility to anyone for the consequences of using it
9: or for whether it serves any particular purpose or works at all,
10: unless he says so in writing. Refer to the X-CHESS General Public
11: License for full details.
12:
13: Everyone is granted permission to copy, modify and redistribute
14: X-CHESS, but only under the conditions described in the
15: X-CHESS General Public License. A copy of this license is
16: supposed to have been given to you along with X-CHESS so you
17: can know your rights and responsibilities. It should be in a
18: file named COPYING. Among other things, the copyright notice
19: and this notice must be preserved on all copies. */
20:
21:
22: /* RCS Info: $Revision: 1.4 $ on $Date: 86/11/23 17:17:32 $
23: * $Source: /users/faustus/xchess/RCS/control.c,v $
24: * Copyright (c) 1986 Wayne A. Christopher, U. C. Berkeley CAD Group
25: * Permission is granted to do anything with this code except sell it
26: * or remove this message.
27: *
28: * Deal with input from the user.
29: */
30:
31: #include "xchess.h"
32:
33: move *moves;
34: move *foremoves;
35: color nexttomove = WHITE;
36: bool noisyflag = false;
37:
38: move *lastmove;
39: static move *thismove;
40:
41: static void screen_move();
42:
43: void
44: button_pressed(event, win)
45: XEvent *event;
46: windata *win;
47: {
48: int x, y;
49: XKeyEvent *ev = (XKeyEvent *) event;
50:
51: if (!oneboard && (win->color != nexttomove)) {
52: message_add(win, "Wrong player!\n", true);
53: return;
54: }
55: if (progflag && (nexttomove == (blackflag ? WHITE : BLACK))) {
56: message_add(win, "Wait for the computer...\n", true);
57: return;
58: }
59: if (loading_flag) {
60: message_add(win, "You'd better not do that now...\n", true);
61: return;
62: }
63:
64: /* Figure out what piece he is pointing at. */
65: x = ev->x / (SQUARE_WIDTH + BORDER_WIDTH);
66: y = ev->y / (SQUARE_HEIGHT + BORDER_WIDTH);
67:
68: if (win->flipped) {
69: y = SIZE - y - 1;
70: x = SIZE - x - 1;
71: }
72:
73: if ((x < 0) || (x >= SIZE) || (y < 0) || (y >= SIZE)) {
74: fprintf(stderr, "Bad coords (%d, %d)\n", x, y);
75: return;
76: }
77:
78: if (oneboard && (chessboard->square[y][x].color != nexttomove)) {
79: message_add(win, "Wrong player!\n", true);
80: return;
81: } else if (!oneboard && (chessboard->square[y][x].color !=
82: win->color)) {
83: message_add(win, "Can't move that\n", true);
84: return;
85: }
86:
87: thismove = alloc(move);
88: thismove->fromx = x;
89: thismove->fromy = y;
90: thismove->piece.color = chessboard->square[y][x].color;
91: thismove->piece.type = chessboard->square[y][x].type;
92:
93: if (debug)
94: fprintf(stderr, "%s selected his %s at (%d, %d)...\n",
95: colornames[(int) thismove->piece.color],
96: piecenames[(int) thismove->piece.type],
97: thismove->fromy, thismove->fromx);
98: return;
99: }
100:
101: void
102: button_released(event, win)
103: XEvent *event;
104: windata *win;
105: {
106: int x, y;
107: XKeyEvent *ev = (XKeyEvent *) event;
108:
109: if (!thismove) {
110: /* fprintf(stderr, "Error: button hasn't been pressed\n"); */
111: return;
112: }
113: if (loading_flag)
114: return;
115:
116: /* Figure out what piece he is pointing at. */
117: x = ev->x / (SQUARE_WIDTH + BORDER_WIDTH);
118: y = ev->y / (SQUARE_HEIGHT + BORDER_WIDTH);
119:
120: if (win->flipped) {
121: y = SIZE - y - 1;
122: x = SIZE - x - 1;
123: }
124:
125: if ((x < 0) || (x >= SIZE) || (y < 0) || (y >= SIZE)) {
126: fprintf(stderr, "Bad coords (%d, %d)\n", x, y);
127: return;
128: }
129:
130: if ((thismove->fromx == x) && (thismove->fromy == y)) {
131: message_add(win, "Hey, you touch it, you move it, buddy.\n",
132: true);
133: return;
134: }
135: if (chessboard->square[y][x].color == thismove->piece.color) {
136: message_add(win, "Can't put one piece on top of another\n",
137: true);
138: return;
139: }
140:
141: thismove->tox = x;
142: thismove->toy = y;
143: thismove->taken.color = chessboard->square[y][x].color;
144: thismove->taken.type = chessboard->square[y][x].type;
145: if (thismove->taken.color != NONE)
146: thismove->type = CAPTURE;
147: else if ((thismove->piece.type == KING) && (thismove->fromx == 4) &&
148: (thismove->tox == 6) &&
149: (thismove->toy == thismove->fromy))
150: thismove->type = KCASTLE;
151: else if ((thismove->piece.type == KING) && (thismove->tox == 2) &&
152: (thismove->fromx == 4) &&
153: (thismove->toy == thismove->fromy))
154: thismove->type = QCASTLE;
155: else
156: thismove->type = MOVE;
157:
158: /* Now check the en-passant case... */
159: if ((thismove->type == MOVE) && ((thismove->tox == thismove->fromx + 1)
160: || (thismove->tox == thismove->fromx - 1)) &&
161: (thismove->piece.type == PAWN) && lastmove &&
162: (lastmove->tox == lastmove->fromx) && (lastmove->fromx
163: == thismove->tox) && ((lastmove->fromy + lastmove->toy)
164: / 2 == thismove->toy)) {
165: thismove->type = CAPTURE;
166: thismove->enpassant = true;
167: thismove->taken = lastmove->piece;
168: }
169:
170: if (!valid_move(thismove, chessboard)) {
171: message_add(win, "Invalid move.\n", true);
172: return;
173: }
174:
175: if (debug)
176: fprintf(stderr, "\t... and moved it to (%d, %d), type %s\n",
177: thismove->toy, thismove->tox,
178: movetypenames[(int) thismove->type]);
179: move_piece(thismove);
180:
181: if (thismove->check) {
182: message_add(win1, "Check.\n", true);
183: if (!oneboard) {
184: message_add(win2, "Check.\n", true);
185: }
186: }
187:
188: if (!moves)
189: moves = lastmove = thismove;
190: else
191: lastmove = lastmove->next = thismove;
192:
193: if (progflag)
194: program_send(thismove);
195:
196: thismove = NULL;
197: nexttomove = ((nexttomove == WHITE) ? BLACK : WHITE);
198: clock_switch();
199:
200: return;
201: }
202:
203: void
204: prog_move(m)
205: move *m;
206: {
207: if (debug)
208: fprintf(stderr, "program moves from (%d, %d) to (%d, %d)\n",
209: m->fromy, m->fromx, m->toy, m->tox);
210: move_piece(m);
211:
212: if (!moves)
213: moves = lastmove = m;
214: else
215: lastmove = lastmove->next = m;
216:
217: nexttomove = ((nexttomove == WHITE) ? BLACK : WHITE);
218: clock_switch();
219:
220: return;
221: }
222:
223: void
224: move_piece(m)
225: move *m;
226: {
227: /* Update the screen... */
228: screen_move(m);
229:
230: /* Move the piece on the board... */
231: board_move(chessboard, m);
232:
233: /* And record it... */
234: record_move(m);
235:
236: if (noisyflag) {
237: XBell(win1->display, 50);
238: XBell(win2->display, 50);
239: }
240: return;
241: }
242:
243: static void
244: screen_move(m)
245: move *m;
246: {
247: piece pp;
248:
249: switch (m->type) {
250: case CAPTURE:
251: jail_add(&m->taken);
252: /* FALLTHRU */
253:
254: case MOVE:
255: win_erasepiece(m->fromy, m->fromx, WHITE);
256: if (win_flashmove)
257: win_flash(m, WHITE);
258: win_drawpiece(&m->piece, m->toy, m->tox, WHITE);
259: if (m->enpassant)
260: win_erasepiece(m->toy + ((m->piece.color == WHITE) ?
261: 1 : -1), m->tox, WHITE);
262: if (!oneboard) {
263: win_erasepiece(m->fromy, m->fromx, BLACK);
264: if (win_flashmove)
265: win_flash(m, BLACK);
266: win_drawpiece(&m->piece, m->toy, m->tox, BLACK);
267: if (m->enpassant)
268: win_erasepiece(m->toy + ((m->piece.color ==
269: WHITE) ? 1 : -1), m->tox, WHITE);
270: }
271: if ((m->piece.type == PAWN) && (((m->piece.color == BLACK) &&
272: (m->toy == 7)) || ((m->piece.color == WHITE) &&
273: (m->toy == 0)))) {
274: pp.color = m->piece.color;
275: pp.type = QUEEN;
276: win_drawpiece(&pp, m->toy, m->tox, WHITE);
277: if (!oneboard)
278: win_drawpiece(&m->piece, m->toy, m->tox, BLACK);
279: }
280: break;
281:
282: case KCASTLE:
283: if (m->piece.color == WHITE) {
284: win_erasepiece(7, 4, WHITE);
285: win_erasepiece(7, 7, WHITE);
286: if (win_flashmove)
287: win_flash(m, WHITE);
288: win_drawpiece(&m->piece, 7, 6, WHITE);
289: win_drawpiece(&chessboard->square[7][7], 7, 5, WHITE);
290: if (!oneboard) {
291: win_erasepiece(7, 4, BLACK);
292: win_erasepiece(7, 7, BLACK);
293: if (win_flashmove)
294: win_flash(m, BLACK);
295: win_drawpiece(&m->piece, 7, 6, BLACK);
296: win_drawpiece(&chessboard->square[7][7], 7, 5,
297: BLACK);
298: }
299: } else {
300: win_erasepiece(0, 4, WHITE);
301: win_erasepiece(0, 7, WHITE);
302: if (win_flashmove)
303: win_flash(m, WHITE);
304: win_drawpiece(&m->piece, 0, 6, WHITE);
305: win_drawpiece(&chessboard->square[0][7], 0, 5, WHITE);
306: if (!oneboard) {
307: win_erasepiece(0, 4, BLACK);
308: win_erasepiece(0, 7, BLACK);
309: if (win_flashmove)
310: win_flash(m, BLACK);
311: win_drawpiece(&m->piece, 0, 6, BLACK);
312: win_drawpiece(&chessboard->square[0][7], 0, 5,
313: BLACK);
314: }
315: }
316: break;
317:
318: case QCASTLE:
319: if (m->piece.color == WHITE) {
320: win_erasepiece(7, 4, WHITE);
321: win_erasepiece(7, 0, WHITE);
322: if (win_flashmove)
323: win_flash(m, WHITE);
324: win_drawpiece(&m->piece, 7, 2, WHITE);
325: win_drawpiece(&chessboard->square[7][0], 7, 3, WHITE);
326: if (!oneboard) {
327: win_erasepiece(7, 4, BLACK);
328: win_erasepiece(7, 0, BLACK);
329: if (win_flashmove)
330: win_flash(m, BLACK);
331: win_drawpiece(&m->piece, 7, 2, BLACK);
332: win_drawpiece(&chessboard->square[7][7], 7, 3,
333: BLACK);
334: }
335: } else {
336: win_erasepiece(0, 4, WHITE);
337: win_erasepiece(0, 0, WHITE);
338: if (win_flashmove)
339: win_flash(m, WHITE);
340: win_drawpiece(&m->piece, 0, 2, WHITE);
341: win_drawpiece(&chessboard->square[0][0], 0, 3, WHITE);
342: if (!oneboard) {
343: win_erasepiece(0, 4, BLACK);
344: win_erasepiece(0, 0, BLACK);
345: if (win_flashmove)
346: win_flash(m, BLACK);
347: win_drawpiece(&m->piece, 0, 2, BLACK);
348: win_drawpiece(&chessboard->square[0][7], 0, 3,
349: BLACK);
350: }
351: }
352: break;
353:
354: default:
355: fprintf(stderr, "Bad move type %d\n", m->type);
356: }
357: return;
358: }
359:
360: /* Retract the last move made... */
361:
362: void
363: replay()
364: {
365: move *m = lastmove, bm;
366:
367: memset(&bm, 0, sizeof(bm));
368: switch (m->type) {
369: case MOVE:
370: bm.type = MOVE;
371: bm.piece = m->piece;
372: bm.fromx = m->tox;
373: bm.fromy = m->toy;
374: bm.tox = m->fromx;
375: bm.toy = m->fromy;
376: board_move(chessboard, &bm);
377: screen_move(&bm);
378: break;
379:
380: case CAPTURE:
381: bm.type = MOVE;
382: bm.piece = m->piece;
383: bm.fromx = m->tox;
384: bm.fromy = m->toy;
385: bm.tox = m->fromx;
386: bm.toy = m->fromy;
387: board_move(chessboard, &bm);
388: screen_move(&bm);
389: chessboard->square[m->toy][m->tox] = m->taken;
390: bm.piece = m->taken;
391: bm.fromx = bm.tox = m->tox;
392: bm.fromy = bm.toy = m->toy;
393: screen_move(&bm);
394: jail_remove(&m->taken);
395: break;
396:
397: case KCASTLE:
398: bm.type = MOVE;
399: bm.piece.type = KING;
400: bm.piece.color = m->piece.color;
401: bm.fromx = 6;
402: bm.tox = 4;
403: bm.fromy = bm.toy = (m->piece.color == WHITE) ? 7 : 0;
404: board_move(chessboard, &bm);
405: screen_move(&bm);
406: bm.type = MOVE;
407: bm.piece.type = ROOK;
408: bm.piece.color = m->piece.color;
409: bm.fromx = 5;
410: bm.tox = 7;
411: bm.fromy = bm.toy = (m->piece.color == WHITE) ? 7 : 0;
412: board_move(chessboard, &bm);
413: screen_move(&bm);
414: if (m->piece.color == WHITE)
415: chessboard->white_cant_castle_k = false;
416: else
417: chessboard->black_cant_castle_k = false;
418: break;
419:
420: case QCASTLE:
421: bm.type = MOVE;
422: bm.piece.type = KING;
423: bm.piece.color = m->piece.color;
424: bm.fromx = 2;
425: bm.tox = 4;
426: bm.fromy = bm.toy = (m->piece.color == WHITE) ? 7 : 0;
427: board_move(chessboard, &bm);
428: screen_move(&bm);
429: bm.type = MOVE;
430: bm.piece.type = ROOK;
431: bm.piece.color = m->piece.color;
432: bm.fromx = 3;
433: bm.tox = 0;
434: bm.fromy = bm.toy = (m->piece.color == WHITE) ? 7 : 0;
435: board_move(chessboard, &bm);
436: screen_move(&bm);
437: if (m->piece.color == WHITE)
438: chessboard->white_cant_castle_q = false;
439: else
440: chessboard->black_cant_castle_q = false;
441: break;
442: }
443: record_back();
444:
445: nexttomove = ((nexttomove == WHITE) ? BLACK : WHITE);
446: clock_switch();
447:
448: if (!moves->next) {
449: moves->next = foremoves;
450: foremoves = moves;
451: moves = lastmove = NULL;
452: } else {
453: for (m = moves; m->next; m = m->next)
454: lastmove = m;
455: lastmove->next->next = foremoves;
456: foremoves = lastmove->next;
457: lastmove->next = NULL;
458: }
459:
460: if (progflag)
461: program_undo();
462:
463: return;
464: }
465:
466: /* Put back the last move undone. */
467:
468: void
469: forward()
470: {
471: prog_move(foremoves);
472: foremoves = foremoves->next;
473: return;
474: }
475:
476: /* End the game. */
477:
478: void
479: cleanup(s)
480: char *s;
481: {
482: if (progflag)
483: program_end();
484: record_end(s);
485: XSync(win1->display, 0);
486: if (!oneboard) {
487: XSync(win2->display, 0);
488: }
489: exit(0);
490: }
491:
492: void
493: restart()
494: {
495: moves = lastmove = thismove = NULL;
496: nexttomove = WHITE;
497:
498: clock_init(win1, WHITE);
499: clock_init(win1, BLACK);
500: jail_init(win1);
501: if (!oneboard) {
502: clock_init(win2, WHITE);
503: clock_init(win2, BLACK);
504: jail_init(win2);
505: }
506: board_init(chessboard);
507: win_restart();
508: record_reset();
509: if (progflag) {
510: program_end();
511: program_init(progname);
512: }
513: return;
514: }
515:
This archive runs on limited infrastructure. Preserving old code on modern bandwidth. Automated agents are requested to crawl responsibly.