diff options
Diffstat (limited to 'gnu/games/chess/Xchess/control.c')
| -rw-r--r-- | gnu/games/chess/Xchess/control.c | 515 |
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; +} + |
