summaryrefslogtreecommitdiff
path: root/gnu/games/chess/Xchess/control.c
diff options
context:
space:
mode:
Diffstat (limited to 'gnu/games/chess/Xchess/control.c')
-rw-r--r--gnu/games/chess/Xchess/control.c515
1 files changed, 515 insertions, 0 deletions
diff --git a/gnu/games/chess/Xchess/control.c b/gnu/games/chess/Xchess/control.c
new file mode 100644
index 000000000000..8591bd7176da
--- /dev/null
+++ b/gnu/games/chess/Xchess/control.c
@@ -0,0 +1,515 @@
+/* This file contains code for X-CHESS.
+ Copyright (C) 1986 Free Software Foundation, Inc.
+
+This file is part of X-CHESS.
+
+X-CHESS is distributed in the hope that it will be useful,
+but WITHOUT ANY WARRANTY. No author or distributor
+accepts responsibility to anyone for the consequences of using it
+or for whether it serves any particular purpose or works at all,
+unless he says so in writing. Refer to the X-CHESS General Public
+License for full details.
+
+Everyone is granted permission to copy, modify and redistribute
+X-CHESS, but only under the conditions described in the
+X-CHESS General Public License. A copy of this license is
+supposed to have been given to you along with X-CHESS so you
+can know your rights and responsibilities. It should be in a
+file named COPYING. Among other things, the copyright notice
+and this notice must be preserved on all copies. */
+
+
+/* RCS Info: $Revision: 1.1.1.1 $ on $Date: 1993/06/12 14:41:11 $
+ * $Source: /home/cvs/386BSD/src/gnu/games/chess/Xchess/control.c,v $
+ * Copyright (c) 1986 Wayne A. Christopher, U. C. Berkeley CAD Group
+ * Permission is granted to do anything with this code except sell it
+ * or remove this message.
+ *
+ * Deal with input from the user.
+ */
+
+#include "xchess.h"
+
+move *moves;
+move *foremoves;
+color nexttomove = WHITE;
+bool noisyflag = false;
+
+move *lastmove;
+static move *thismove;
+
+static void screen_move();
+
+void
+button_pressed(event, win)
+ XEvent *event;
+ windata *win;
+{
+ int x, y;
+ XKeyEvent *ev = (XKeyEvent *) event;
+
+ if (!oneboard && (win->color != nexttomove)) {
+ message_add(win, "Wrong player!\n", true);
+ return;
+ }
+ if (progflag && (nexttomove == (blackflag ? WHITE : BLACK))) {
+ message_add(win, "Wait for the computer...\n", true);
+ return;
+ }
+ if (loading_flag) {
+ message_add(win, "You'd better not do that now...\n", true);
+ return;
+ }
+
+ /* Figure out what piece he is pointing at. */
+ x = ev->x / (SQUARE_WIDTH + BORDER_WIDTH);
+ y = ev->y / (SQUARE_HEIGHT + BORDER_WIDTH);
+
+ if (win->flipped) {
+ y = SIZE - y - 1;
+ x = SIZE - x - 1;
+ }
+
+ if ((x < 0) || (x >= SIZE) || (y < 0) || (y >= SIZE)) {
+ fprintf(stderr, "Bad coords (%d, %d)\n", x, y);
+ return;
+ }
+
+ if (oneboard && (chessboard->square[y][x].color != nexttomove)) {
+ message_add(win, "Wrong player!\n", true);
+ return;
+ } else if (!oneboard && (chessboard->square[y][x].color !=
+ win->color)) {
+ message_add(win, "Can't move that\n", true);
+ return;
+ }
+
+ thismove = alloc(move);
+ thismove->fromx = x;
+ thismove->fromy = y;
+ thismove->piece.color = chessboard->square[y][x].color;
+ thismove->piece.type = chessboard->square[y][x].type;
+
+ if (debug)
+ fprintf(stderr, "%s selected his %s at (%d, %d)...\n",
+ colornames[(int) thismove->piece.color],
+ piecenames[(int) thismove->piece.type],
+ thismove->fromy, thismove->fromx);
+ return;
+}
+
+void
+button_released(event, win)
+ XEvent *event;
+ windata *win;
+{
+ int x, y;
+ XKeyEvent *ev = (XKeyEvent *) event;
+
+ if (!thismove) {
+ /* fprintf(stderr, "Error: button hasn't been pressed\n"); */
+ return;
+ }
+ if (loading_flag)
+ return;
+
+ /* Figure out what piece he is pointing at. */
+ x = ev->x / (SQUARE_WIDTH + BORDER_WIDTH);
+ y = ev->y / (SQUARE_HEIGHT + BORDER_WIDTH);
+
+ if (win->flipped) {
+ y = SIZE - y - 1;
+ x = SIZE - x - 1;
+ }
+
+ if ((x < 0) || (x >= SIZE) || (y < 0) || (y >= SIZE)) {
+ fprintf(stderr, "Bad coords (%d, %d)\n", x, y);
+ return;
+ }
+
+ if ((thismove->fromx == x) && (thismove->fromy == y)) {
+ message_add(win, "Hey, you touch it, you move it, buddy.\n",
+ true);
+ return;
+ }
+ if (chessboard->square[y][x].color == thismove->piece.color) {
+ message_add(win, "Can't put one piece on top of another\n",
+ true);
+ return;
+ }
+
+ thismove->tox = x;
+ thismove->toy = y;
+ thismove->taken.color = chessboard->square[y][x].color;
+ thismove->taken.type = chessboard->square[y][x].type;
+ if (thismove->taken.color != NONE)
+ thismove->type = CAPTURE;
+ else if ((thismove->piece.type == KING) && (thismove->fromx == 4) &&
+ (thismove->tox == 6) &&
+ (thismove->toy == thismove->fromy))
+ thismove->type = KCASTLE;
+ else if ((thismove->piece.type == KING) && (thismove->tox == 2) &&
+ (thismove->fromx == 4) &&
+ (thismove->toy == thismove->fromy))
+ thismove->type = QCASTLE;
+ else
+ thismove->type = MOVE;
+
+ /* Now check the en-passant case... */
+ if ((thismove->type == MOVE) && ((thismove->tox == thismove->fromx + 1)
+ || (thismove->tox == thismove->fromx - 1)) &&
+ (thismove->piece.type == PAWN) && lastmove &&
+ (lastmove->tox == lastmove->fromx) && (lastmove->fromx
+ == thismove->tox) && ((lastmove->fromy + lastmove->toy)
+ / 2 == thismove->toy)) {
+ thismove->type = CAPTURE;
+ thismove->enpassant = true;
+ thismove->taken = lastmove->piece;
+ }
+
+ if (!valid_move(thismove, chessboard)) {
+ message_add(win, "Invalid move.\n", true);
+ return;
+ }
+
+ if (debug)
+ fprintf(stderr, "\t... and moved it to (%d, %d), type %s\n",
+ thismove->toy, thismove->tox,
+ movetypenames[(int) thismove->type]);
+ move_piece(thismove);
+
+ if (thismove->check) {
+ message_add(win1, "Check.\n", true);
+ if (!oneboard) {
+ message_add(win2, "Check.\n", true);
+ }
+ }
+
+ if (!moves)
+ moves = lastmove = thismove;
+ else
+ lastmove = lastmove->next = thismove;
+
+ if (progflag)
+ program_send(thismove);
+
+ thismove = NULL;
+ nexttomove = ((nexttomove == WHITE) ? BLACK : WHITE);
+ clock_switch();
+
+ return;
+}
+
+void
+prog_move(m)
+ move *m;
+{
+ if (debug)
+ fprintf(stderr, "program moves from (%d, %d) to (%d, %d)\n",
+ m->fromy, m->fromx, m->toy, m->tox);
+ move_piece(m);
+
+ if (!moves)
+ moves = lastmove = m;
+ else
+ lastmove = lastmove->next = m;
+
+ nexttomove = ((nexttomove == WHITE) ? BLACK : WHITE);
+ clock_switch();
+
+ return;
+}
+
+void
+move_piece(m)
+ move *m;
+{
+ /* Update the screen... */
+ screen_move(m);
+
+ /* Move the piece on the board... */
+ board_move(chessboard, m);
+
+ /* And record it... */
+ record_move(m);
+
+ if (noisyflag) {
+ XBell(win1->display, 50);
+ XBell(win2->display, 50);
+ }
+ return;
+}
+
+static void
+screen_move(m)
+ move *m;
+{
+ piece pp;
+
+ switch (m->type) {
+ case CAPTURE:
+ jail_add(&m->taken);
+ /* FALLTHRU */
+
+ case MOVE:
+ win_erasepiece(m->fromy, m->fromx, WHITE);
+ if (win_flashmove)
+ win_flash(m, WHITE);
+ win_drawpiece(&m->piece, m->toy, m->tox, WHITE);
+ if (m->enpassant)
+ win_erasepiece(m->toy + ((m->piece.color == WHITE) ?
+ 1 : -1), m->tox, WHITE);
+ if (!oneboard) {
+ win_erasepiece(m->fromy, m->fromx, BLACK);
+ if (win_flashmove)
+ win_flash(m, BLACK);
+ win_drawpiece(&m->piece, m->toy, m->tox, BLACK);
+ if (m->enpassant)
+ win_erasepiece(m->toy + ((m->piece.color ==
+ WHITE) ? 1 : -1), m->tox, WHITE);
+ }
+ if ((m->piece.type == PAWN) && (((m->piece.color == BLACK) &&
+ (m->toy == 7)) || ((m->piece.color == WHITE) &&
+ (m->toy == 0)))) {
+ pp.color = m->piece.color;
+ pp.type = QUEEN;
+ win_drawpiece(&pp, m->toy, m->tox, WHITE);
+ if (!oneboard)
+ win_drawpiece(&m->piece, m->toy, m->tox, BLACK);
+ }
+ break;
+
+ case KCASTLE:
+ if (m->piece.color == WHITE) {
+ win_erasepiece(7, 4, WHITE);
+ win_erasepiece(7, 7, WHITE);
+ if (win_flashmove)
+ win_flash(m, WHITE);
+ win_drawpiece(&m->piece, 7, 6, WHITE);
+ win_drawpiece(&chessboard->square[7][7], 7, 5, WHITE);
+ if (!oneboard) {
+ win_erasepiece(7, 4, BLACK);
+ win_erasepiece(7, 7, BLACK);
+ if (win_flashmove)
+ win_flash(m, BLACK);
+ win_drawpiece(&m->piece, 7, 6, BLACK);
+ win_drawpiece(&chessboard->square[7][7], 7, 5,
+ BLACK);
+ }
+ } else {
+ win_erasepiece(0, 4, WHITE);
+ win_erasepiece(0, 7, WHITE);
+ if (win_flashmove)
+ win_flash(m, WHITE);
+ win_drawpiece(&m->piece, 0, 6, WHITE);
+ win_drawpiece(&chessboard->square[0][7], 0, 5, WHITE);
+ if (!oneboard) {
+ win_erasepiece(0, 4, BLACK);
+ win_erasepiece(0, 7, BLACK);
+ if (win_flashmove)
+ win_flash(m, BLACK);
+ win_drawpiece(&m->piece, 0, 6, BLACK);
+ win_drawpiece(&chessboard->square[0][7], 0, 5,
+ BLACK);
+ }
+ }
+ break;
+
+ case QCASTLE:
+ if (m->piece.color == WHITE) {
+ win_erasepiece(7, 4, WHITE);
+ win_erasepiece(7, 0, WHITE);
+ if (win_flashmove)
+ win_flash(m, WHITE);
+ win_drawpiece(&m->piece, 7, 2, WHITE);
+ win_drawpiece(&chessboard->square[7][0], 7, 3, WHITE);
+ if (!oneboard) {
+ win_erasepiece(7, 4, BLACK);
+ win_erasepiece(7, 0, BLACK);
+ if (win_flashmove)
+ win_flash(m, BLACK);
+ win_drawpiece(&m->piece, 7, 2, BLACK);
+ win_drawpiece(&chessboard->square[7][7], 7, 3,
+ BLACK);
+ }
+ } else {
+ win_erasepiece(0, 4, WHITE);
+ win_erasepiece(0, 0, WHITE);
+ if (win_flashmove)
+ win_flash(m, WHITE);
+ win_drawpiece(&m->piece, 0, 2, WHITE);
+ win_drawpiece(&chessboard->square[0][0], 0, 3, WHITE);
+ if (!oneboard) {
+ win_erasepiece(0, 4, BLACK);
+ win_erasepiece(0, 0, BLACK);
+ if (win_flashmove)
+ win_flash(m, BLACK);
+ win_drawpiece(&m->piece, 0, 2, BLACK);
+ win_drawpiece(&chessboard->square[0][7], 0, 3,
+ BLACK);
+ }
+ }
+ break;
+
+ default:
+ fprintf(stderr, "Bad move type %d\n", m->type);
+ }
+ return;
+}
+
+/* Retract the last move made... */
+
+void
+replay()
+{
+ move *m = lastmove, bm;
+
+ memset(&bm, 0, sizeof(bm));
+ switch (m->type) {
+ case MOVE:
+ bm.type = MOVE;
+ bm.piece = m->piece;
+ bm.fromx = m->tox;
+ bm.fromy = m->toy;
+ bm.tox = m->fromx;
+ bm.toy = m->fromy;
+ board_move(chessboard, &bm);
+ screen_move(&bm);
+ break;
+
+ case CAPTURE:
+ bm.type = MOVE;
+ bm.piece = m->piece;
+ bm.fromx = m->tox;
+ bm.fromy = m->toy;
+ bm.tox = m->fromx;
+ bm.toy = m->fromy;
+ board_move(chessboard, &bm);
+ screen_move(&bm);
+ chessboard->square[m->toy][m->tox] = m->taken;
+ bm.piece = m->taken;
+ bm.fromx = bm.tox = m->tox;
+ bm.fromy = bm.toy = m->toy;
+ screen_move(&bm);
+ jail_remove(&m->taken);
+ break;
+
+ case KCASTLE:
+ bm.type = MOVE;
+ bm.piece.type = KING;
+ bm.piece.color = m->piece.color;
+ bm.fromx = 6;
+ bm.tox = 4;
+ bm.fromy = bm.toy = (m->piece.color == WHITE) ? 7 : 0;
+ board_move(chessboard, &bm);
+ screen_move(&bm);
+ bm.type = MOVE;
+ bm.piece.type = ROOK;
+ bm.piece.color = m->piece.color;
+ bm.fromx = 5;
+ bm.tox = 7;
+ bm.fromy = bm.toy = (m->piece.color == WHITE) ? 7 : 0;
+ board_move(chessboard, &bm);
+ screen_move(&bm);
+ if (m->piece.color == WHITE)
+ chessboard->white_cant_castle_k = false;
+ else
+ chessboard->black_cant_castle_k = false;
+ break;
+
+ case QCASTLE:
+ bm.type = MOVE;
+ bm.piece.type = KING;
+ bm.piece.color = m->piece.color;
+ bm.fromx = 2;
+ bm.tox = 4;
+ bm.fromy = bm.toy = (m->piece.color == WHITE) ? 7 : 0;
+ board_move(chessboard, &bm);
+ screen_move(&bm);
+ bm.type = MOVE;
+ bm.piece.type = ROOK;
+ bm.piece.color = m->piece.color;
+ bm.fromx = 3;
+ bm.tox = 0;
+ bm.fromy = bm.toy = (m->piece.color == WHITE) ? 7 : 0;
+ board_move(chessboard, &bm);
+ screen_move(&bm);
+ if (m->piece.color == WHITE)
+ chessboard->white_cant_castle_q = false;
+ else
+ chessboard->black_cant_castle_q = false;
+ break;
+ }
+ record_back();
+
+ nexttomove = ((nexttomove == WHITE) ? BLACK : WHITE);
+ clock_switch();
+
+ if (!moves->next) {
+ moves->next = foremoves;
+ foremoves = moves;
+ moves = lastmove = NULL;
+ } else {
+ for (m = moves; m->next; m = m->next)
+ lastmove = m;
+ lastmove->next->next = foremoves;
+ foremoves = lastmove->next;
+ lastmove->next = NULL;
+ }
+
+ if (progflag)
+ program_undo();
+
+ return;
+}
+
+/* Put back the last move undone. */
+
+void
+forward()
+{
+ prog_move(foremoves);
+ foremoves = foremoves->next;
+ return;
+}
+
+/* End the game. */
+
+void
+cleanup(s)
+ char *s;
+{
+ if (progflag)
+ program_end();
+ record_end(s);
+ XSync(win1->display, 0);
+ if (!oneboard) {
+ XSync(win2->display, 0);
+ }
+ exit(0);
+}
+
+void
+restart()
+{
+ moves = lastmove = thismove = NULL;
+ nexttomove = WHITE;
+
+ clock_init(win1, WHITE);
+ clock_init(win1, BLACK);
+ jail_init(win1);
+ if (!oneboard) {
+ clock_init(win2, WHITE);
+ clock_init(win2, BLACK);
+ jail_init(win2);
+ }
+ board_init(chessboard);
+ win_restart();
+ record_reset();
+ if (progflag) {
+ program_end();
+ program_init(progname);
+ }
+ return;
+}
+