home
***
CD-ROM
|
disk
|
FTP
|
other
***
search
/
Usenet 1994 October
/
usenetsourcesnewsgroupsinfomagicoctober1994disk2.iso
/
games
/
volume11
/
reve
/
part05
/
boardstuff.c
next >
Wrap
C/C++ Source or Header
|
1990-11-15
|
12KB
|
509 lines
/*LINTLIBRARY*/
/* @(#)boardstuff.c 1.9 90/10/20
*
* Various board routines used by reve.
*
* Copyright (C) 1990 - Rich Burridge & Yves Gallot.
* All rights reserved.
*
* Permission is given to distribute these sources, as long as the
* introductory messages are not removed, and no monies are exchanged.
*
* You are forbidden from using Reve as is, or in a modified state, in
* any tournaments, without the permission of the authors.
*
* No responsibility is taken for any errors on inaccuracies inherent
* either to the comments or the code of this program, but if reported
* (see README file), then an attempt will be made to fix them.
*/
#include <stdio.h>
#include <ctype.h>
#ifndef SYSV
#include <sys/time.h>
#endif /*SYSV*/
#include "color.h"
#include "reve.h"
#include "extern.h"
void
animate_move(move)
int move ;
{
int x0, y0, x1, y1, x, y, dx, dy, ctr ;
lock_screen(IS_ON) ;
get_xy(move, &x1, &y1) ;
dx = x1 ;
dy = y1 ;
if (x1 > y1)
{
ctr = dx / 2 ;
x = BBORDER ;
y = BBORDER ;
draw_piece(WHITE, x, CY+y, RINV) ;
while (x < x1)
{
#ifndef SYSV
set_timer() ;
#endif /*SYSV*/
x0 = x ;
y0 = y ;
x += move_delta ;
if ((ctr -= dy) < 0)
{
ctr += dx ;
y += move_delta ;
}
draw_piece(WHITE, x, CY+y, RINV) ;
draw_piece(WHITE, x0, CY+y0, RINV) ;
#ifndef SYSV
nap_upto(1) ;
#endif /*SYSV*/
}
draw_piece(WHITE, x, CY+y, RINV) ;
}
else
{
ctr = dy / 2 ;
x = BBORDER ;
y = BBORDER ;
draw_piece(WHITE, x, CY+y, RINV) ;
while (y < y1)
{
#ifndef SYSV
set_timer() ;
#endif /*SYSV*/
x0 = x ;
y0 = y ;
y += move_delta ;
if ((ctr -= dx) < 0)
{
ctr += dy ;
x += move_delta ;
}
draw_piece(WHITE, x, CY+y, RINV) ;
draw_piece(WHITE, x0, CY+y0, RINV) ;
#ifndef SYSV
nap_upto(1) ;
#endif /*SYSV*/
}
draw_piece(WHITE, x, CY+y, RINV) ;
}
lock_screen(IS_OFF) ;
}
/* This routine checks to see if a move can be made for this player.
* If not, various checks are made to see if the game is finished.
* Return value indicates if a move can be made.
*/
check(player)
int player ;
{
if ((!count(&board, BLACK)) || (!count(&board, WHITE)) ||
((count(&board, BLACK) + count(&board, WHITE)) == 64))
{
who_wins() ;
last_cmode = cmode ; /* Save previous value in case of undo. */
cmode = GAME_OVER ;
message(PANEL_MES, "Game over") ;
return(FALSE) ;
}
if ((move = valid_move(&board, player)) == FALSE)
{
SPRINTF(line, "%s is forced to pass",
(player == BLACK) ? "Black" : "White") ;
message(PANEL_MES, line) ;
set_turn(OPPONENT(player)) ;
if ((move = valid_move(&board, OPPONENT(player))) == FALSE)
{
who_wins() ;
last_cmode = cmode ;
cmode = GAME_OVER ;
message(PANEL_MES, "Game over") ;
}
return(FALSE) ;
}
return(TRUE) ;
}
void
computer_move(player)
int player ;
{
for (;;)
if (check(player) == TRUE)
{
think(player) ;
if (check(OPPONENT(player)) == TRUE) break ;
if (cmode == GAME_OVER) break ;
}
else
{
if (cmode != GAME_OVER) cmode = (enum cantype) ((int) cmode - 1) ;
return ;
}
}
count(board, player) /* Count the number of player pieces on the board. */
int player ;
BOARD *board ;
{
int i, n ;
n = 0 ;
FOR_BOARD(i)
if (board->square[i] == player) n++ ;
return(n) ;
}
void
do_move(player)
int player ;
{
int taken ; /* Number of pieces flipped this go. */
taken = formfliplist(move, player) ;
update_board_image(player) ;
SPRINTF(line, "%s took %d %s", (player == BLACK) ? "Black" : "White",
taken, (taken == 1) ? "piece" : "pieces") ;
message(PANEL_MES, line) ;
}
formfliplist(move, player)
int move, player ;
{
int cnt, i, n, old_cnt ;
old_cnt = count(&board, player) ;
FOR_BOARD(i) old_board.square[i] = board.square[i] ;
old_board.moves_left = board.moves_left ;
domove(&old_board, move, &board, player) ;
n = 63 - board.moves_left ;
FOR_BOARD(i) moves[n].square[i] = board.square[i] ;
moves[n].moves_left = board.moves_left ;
moves[n].move = move ;
moves[n].note = note ;
moves[n].player = player ;
cnt = count(&board, player) ;
return(cnt - old_cnt - 1) ;
}
void
initboard() /* Initialise the othello board. */
{
static int ivals[4] = { 27, 28, 35, 36 } ;
static int icolors[4] = { WHITE, BLACK, BLACK, WHITE } ;
int i, j , n ;
for (i = 0; i < 64; i++) moves[i].move = -1 ;
for (n = 0; n < 4; n++)
{
FOR_BOARD(i) moves[n].square[i] = FREE ;
for (j = 0; j <= n; j++) moves[n].square[ivals[j]] = icolors[j] ;
moves[n].player = icolors[n] ;
moves[n].move = ivals[n] ;
moves[n].moves_left = 63 - n ;
}
FOR_BOARD(i) old_board.square[i] = board.square[i] = FREE ;
board.square[27] = WHITE ;
board.square[28] = BLACK ;
board.square[35] = BLACK ;
board.square[36] = WHITE ;
board.moves_left = 60 ;
}
void
load_game()
{
/* Read in a game from file, and setup internal variables accordingly.
*
* Notation in the games file is of the format:
* 1, <C-4> - [ remarks field ]
* 2, - <E-3> [ remarks field ]
*
* The move number is the field before the comma. This is just used as a
* consistency check. Next is the black move or the white move (surronded
* by '<' and '>' characters. Obviously only one piece moves per go, and
* the '-' character is used to signify which piece doesn't move (in case
* one player had to miss a turn.
*
* As each position is added, the board is redisplayed, and if the game is
* not over, the next player can commence.
*/
char buf[MAXLINE], col, *lptr, *mptr, row ;
int moveno, n ;
FILE *fp ;
if ((fp = fopen(gamefile, "r")) == NULL)
{
SPRINTF(buf, "Couldn't open game file: %s", gamefile) ;
message(PANEL_MES, buf) ;
return ;
}
moveno = 0 ;
initboard() ;
last_move = -1 ;
init_canvas() ;
message(NOTES_MES, "") ;
while (fgets(buf, MAXLINE, fp) != NULL)
{
if (buf[0] == '\n' || buf[0] == '#') continue ;
moveno++ ;
SSCANF(buf, "%d", &n) ;
if (n != moveno || n > 60)
{
SPRINTF(buf, "Load error: incorrect move [%d] on line %d", n, move) ;
message(PANEL_MES, buf) ;
return ;
}
lptr = (char *) index(buf, '<') ;
mptr = (char *) index(buf, '-') ;
if (lptr == NULL || mptr == NULL)
{
SPRINTF(buf, "Load error: missing < or - on line %d", move) ;
message(PANEL_MES, buf) ;
return ;
}
if (lptr < mptr) next_player = BLACK ; /* Black move? */
else next_player = WHITE ;
SSCANF(lptr, "<%c-%c>", &row, &col) ;
if (load_move(moveno, row, col) == 0)
{
SPRINTF(buf, "Load error: invalid move <%c-%c> on line %d",
row, col, move) ;
message(PANEL_MES, buf) ;
return ;
}
SPRINTF(buf, "Loaded move %d for %s",
moveno, (next_player == BLACK) ? "black" : "white") ;
message(PANEL_MES, buf) ;
}
FCLOSE(fp) ;
set_score() ;
set_turn(OPPONENT(next_player)) ;
cmode = (enum cantype) (OPPONENT(next_player) + 1) ;
next_player = OPPONENT(next_player) ;
if (check(next_player) == TRUE) return ;
(void) check(OPPONENT(next_player)) ;
}
load_move(n, col, row)
int n, col, row ;
{
int i, taken, x, y ;
if (row < '1' || row > '8') return(0) ;
if (isupper(col)) col = tolower(col) ;
if (col < 'a' || col > 'h') return(0) ;
move = (row - '1') * BOARD_SIZE + (col - 'a') ;
if (legal(move, next_player, &board) == FALSE) return(0) ;
taken = formfliplist(move, next_player) ;
batch(IS_ON) ;
FOR_BOARD(i)
if (board.square[i] != old_board.square[i])
{
get_xy(i, &x, &y) ;
draw_piece(next_player, x, CY+y, RSRC) ;
}
batch(IS_OFF) ;
return(1) ;
}
#ifndef SYSV
void
nap_upto(n) /* Sleep upto n microseconds from start of timer. */
int n ;
{
struct timeval ctp ;
struct timezone ctzp ;
long elapsed ; /* Number of microseconds since timer started. */
GETTIMEOFDAY(&ctp, &ctzp) ;
elapsed = ((ctp.tv_usec - tp.tv_usec) +
(ctp.tv_sec - tp.tv_sec) * 1000000L) / 1000 ;
if (elapsed > n) return ;
usleep((unsigned) (n - elapsed)) ;
}
#endif /*SYSV*/
void
save_game()
{
/* Save the current game status to file.
*
* The notation in the saved games file is of the format:
* 1, <C-4> - [ note : 12345 ]
* 2, - <E-3> [ note : 0 ]
*
* The move number is the field before the comma. This is just used as a
* consistency check. Next is the black move or the white move (surronded
* by '<' and '>' characters. Obviously only one piece moves per go, and
* the '-' character is used to signify which piece doesn't move (in case
* one player had to miss a turn.
*/
char buf[MAXLINE] ;
int n ;
FILE *fp ;
if ((fp = fopen(gamefile, "w")) == NULL)
{
SPRINTF(buf, "Couldn't open game file: %s", gamefile) ;
message(PANEL_MES, buf) ;
return ;
}
for (n = 4; n < 64; n++)
{
if (moves[n].move == -1) break ;
if (moves[n].player == BLACK)
FPRINTF(fp, "%d, <%c-%c> - [ note : %ld ]\n",
n-3, (moves[n].move % 8) + 'a',
(moves[n].move >> 3) + '1', moves[n].note) ;
else
FPRINTF(fp, "%d, - <%c-%c> [ note : %ld ]\n",
n-3, (moves[n].move % 8) + 'a',
(moves[n].move >> 3) + '1', moves[n].note) ;
}
FCLOSE(fp) ;
SPRINTF(buf, "Current game saved in %s", gamefile) ;
message(PANEL_MES, buf) ;
}
void
set_score()
{
SPRINTF(line, "Black: %2d, White: %2d",
count(&board, BLACK), count(&board, WHITE)) ;
message(SCORE_MES, line) ;
}
void
set_turn(player)
int player ;
{
SPRINTF(line, "%s to move", (player == BLACK) ? "Black" : "White") ;
message(TURN_MES, line) ;
}
#ifndef SYSV
void
set_timer()
{
struct timezone tzp ;
GETTIMEOFDAY(&tp, &tzp) ;
}
#endif /*SYSV*/
void
show_suggestion()
{
enum optype rop ;
if (suggestion != -1)
{
rop = RCLR ;
color = (iscolor[(int) cur_dpyno]) ? C_LBROWN : C_WHITE ;
if (iscolor[(int) cur_dpyno]) rop = RSRC ;
draw_line(suggest_x-5, CY+suggest_y-5,
suggest_x+5, CY+suggest_y+5, rop, color) ;
draw_line(suggest_x-5, CY+suggest_y+5,
suggest_x+5, CY+suggest_y-5, rop, color) ;
suggestion = -1 ;
}
}
void
update_board_image(player)
int player ;
{
int flips, i, piece, x, y ;
show_suggestion() ;
for (flips = 0; flips < 4; flips++)
{
batch(IS_ON) ;
FOR_BOARD(i)
{
if (board.square[i] != old_board.square[i])
{
get_xy(i, &x, &y) ;
if (i == move) piece = board.square[i] ;
else
piece = (flips % 2) ? board.square[i] : board.square[i] * -1 ;
draw_piece(piece, x, CY+y, RSRC) ;
}
}
batch(IS_OFF) ;
PAUSE ;
}
set_score() ;
set_turn(OPPONENT(player)) ;
message(TURN_MES, line) ;
if (show_notes)
if ((player == BLACK && items[(int) BLACK_PLAYS].value == COMPUTER) ||
(player == WHITE && items[(int) WHITE_PLAYS].value == COMPUTER))
{
SPRINTF(line, "%s: <%c-%c> note : %ld",
(player == BLACK) ? "Black" : "White",
(move & 7) + 'a', (move >> 3) + '1', note) ;
message(NOTES_MES, line) ;
}
}
void
who_wins()
{
int cs, ps ;
ps = count(&board, WHITE) ;
cs = count(&board, BLACK) ;
if (ps > cs)
{
SPRINTF(line, "White wins %d-%d", ps, cs) ;
message(SCORE_MES, line) ;
}
else if (ps == cs)
{
SPRINTF(line,"A tie %d-%d", ps, cs) ;
message(SCORE_MES, line) ;
}
else
{
SPRINTF(line, "Black wins %d-%d", cs, ps) ;
message(SCORE_MES, line) ;
}
}