|
|
DataMuseum.dkPresents historical artifacts from the history of: DKUUG/EUUG Conference tapes |
This is an automatic "excavation" of a thematic subset of
See our Wiki for more about DKUUG/EUUG Conference tapes Excavated with: AutoArchaeologist - Free & Open Source Software. |
top - metrics - downloadIndex: T o
Length: 18018 (0x4662)
Types: TextFile
Names: »otool.c«
└─⟦b20c6495f⟧ Bits:30007238 EUUGD18: Wien-båndet, efterår 1987
└─⟦this⟧ »EUUGD18/Sun/Othello/otool.c«
/* othello tool @(#)otool.c 1.3 12/10/86 */
/*
* @@@ @@@@@ @ @ @@@@@ @ @ @@@
* @ @ @ @ @ @ @ @ @ @
* @ @ @ @@@@@ @@@ @ @ @ @
* @ @ @ @ @ @ @ @ @ @
* @@@ @ @ @ @@@@@ @@@@@ @@@@@ @@@
*
* OTHELLO - graphics front end to othello game
*
* Edward A. Falk
* Sun Microsystems
*
* Various bugfixes, changes and additions by
* Rich Burridge, Sun Microsystems, Australia
*
* December, 1986
*/
#include "othello.h"
#define PATCHLEVEL 1
/* Compilation parameters: */
#define CELL_WIDTH 40
#define PIECE_MARGIN 5
#define PIECE_RAD (CELL_WIDTH/2 - PIECE_MARGIN)
#ifndef SUN2
#define MOVE_DELTA 1 /* For animation */
#else
#define MOVE_DELTA 3
#endif
#define TOTAL_WIDTH BOARDSIZE*CELL_WIDTH
/* Constants, typedefs, externals, globals, statics, macros. */
static short icon_image[] = { /* Main icon. */
#include "othello.icon"
} ;
DEFINE_ICON_FROM_IMAGE(othello_icon,icon_image) ;
static short hglass_image[] = {
#include <images/hglass.cursor>
} ;
mpr_static(hglass_pr,16,16,1,hglass_image) ;
static short white_image[] = {
#include "white.icon"
} ;
mpr_static(white_icon_pr,64,64,1,white_image) ;
static short black_image[] = {
#include "black.icon"
} ;
mpr_static(black_icon_pr,64,64,1,black_image) ;
char w_who[3][9] = { "You", "Computer", "White" } ;
char w_be[3][4] = { "are", "is", "is" } ;
char b_who[3][9] = { "Computer", "You", "Black" } ;
char b_be[3][4] = { "is", "are", "is" } ;
static Frame base_frame ; /* Assorted globals. */
static Panel panel ;
static Canvas canvas ;
static Panel_item last_but, new_game_but, quit_but, suggest_but ;
static Panel_item panel_mes, score_mes ;
static Panel_item computer_plays_choice, remark_choice ;
static Panel_item aspiration_choice, difficulty_choice ;
static Cursor canvas_cursor,hglass_cursor ;
static Pixwin *canvas_pw ;
static enum cmode {white_start, white_moving,
black_start, black_moving, game_over } canvas_mode ;
static enum pmode {play_black, play_white, play_both} play_mode ;
static int piece_x,piece_y ; /* Current position of moving piece */
/* Variables used externally. */
int aspire ; /* Computers level of aspiration. */
int cretin_flag ;
int last_remark ;
int remark ; /* Indicates if remarks are to be displayed. */
Panel_item remark_mes ;
static int last_move ; /* Last valid computer move. */
static int move ; /* Current move being evaluated. */
static int next_player ; /* Next player (BLACK or WHITE) to move. */
static int suggestion ; /* Positive if a suggested move. */
static int suggest_x,suggest_y ; /* Position of suggested move.*/
static int depth ; /* Depth of search for computers move. */
BOARD old_board ; /* The previous Othello board. */
BOARD board ; /* The Othello board. */
static char line[40] ;
static void canvas_proc() ; /* Proc definitions. */
static void last_proc(), new_game_proc(), quit_proc(), suggest_proc() ;
static void computer_plays_proc(), remark_proc() ;
static void aspiration_proc(), difficulty_proc() ;
static void init_panel() ;
static void canvas_init() ;
main(argc,argv)
int argc ;
char *argv[] ;
{
(void) sprintf(line," Othello. V1.%1d",PATCHLEVEL) ;
base_frame = window_create(NULL, FRAME,
FRAME_ICON, &othello_icon,
FRAME_LABEL, line,
FRAME_SUBWINDOWS_ADJUSTABLE, FALSE,
WIN_ERROR_MSG, "Can't create window.",
FRAME_ARGS, argc,argv,
0) ;
panel = window_create(base_frame, PANEL,
WIN_WIDTH, TOTAL_WIDTH+1,
PANEL_LAYOUT, PANEL_HORIZONTAL,
0) ;
init_panel() ;
window_fit_height(panel) ;
canvas = window_create(base_frame, CANVAS,
WIN_X, 0,
WIN_BELOW, panel,
WIN_CONSUME_KBD_EVENT, WIN_NO_EVENTS,
WIN_EVENT_PROC, canvas_proc,
WIN_HEIGHT, TOTAL_WIDTH+1,
WIN_WIDTH, TOTAL_WIDTH+1,
WIN_IGNORE_PICK_EVENTS, KBD_REQUEST, WIN_ASCII_EVENTS, 0,
/* skip for SUNOS 3.0
CANVAS_FAST_MONO, TRUE, */
0) ;
window_fit(base_frame) ;
canvas_pw = (Pixwin *) window_get(canvas,CANVAS_PIXWIN) ;
canvas_cursor = window_get(canvas,WIN_CURSOR) ;
hglass_cursor = cursor_create(CURSOR_IMAGE,&hglass_pr,0) ;
remark = TRUE ;
last_move = -1 ;
play_mode = play_black ;
canvas_mode = white_start ;
initboard() ;
get_remarks() ;
aspire = INIT_ASPIRE ;
depth = INIT_DEPTH ;
cretin_flag = FALSE ;
last_remark = FIRST_REMARK ; /* Force a remark the first time. */
canvas_init() ;
window_main_loop(base_frame) ;
exit(0) ;
}
initboard() /* Initialise the othello board. */
{
int i ;
FOR_BOARD(i) old_board.SQUARE[i] = board.SQUARE[i] = FREE ;
board.SQUARE[27] = BLACK ;
board.SQUARE[28] = WHITE ;
board.SQUARE[35] = WHITE ;
board.SQUARE[36] = BLACK ;
board.MOVES_LEFT = 60 ;
}
static void init_panel()
{
last_but = panel_create_item(panel,PANEL_BUTTON,
PANEL_NOTIFY_PROC,last_proc,
PANEL_LABEL_IMAGE,
panel_button_image(panel,"last",4,(struct pixfont *) 0),
0) ;
new_game_but = panel_create_item(panel,PANEL_BUTTON,
PANEL_NOTIFY_PROC,new_game_proc,
PANEL_LABEL_IMAGE,
panel_button_image(panel,"new game",8,(struct pixfont *) 0),
0) ;
quit_but = panel_create_item(panel,PANEL_BUTTON,
PANEL_NOTIFY_PROC,quit_proc,
PANEL_LABEL_IMAGE,
panel_button_image(panel,"quit",4,(struct pixfont *) 0),
0) ;
suggest_but = panel_create_item(panel,PANEL_BUTTON,
PANEL_NOTIFY_PROC,suggest_proc,
PANEL_LABEL_IMAGE,
panel_button_image(panel,"suggest",7,(struct pixfont *) 0),
0) ;
aspiration_choice = panel_create_item(panel,PANEL_CYCLE,
PANEL_NOTIFY_PROC,aspiration_proc,
PANEL_LABEL_BOLD,TRUE,
PANEL_LABEL_STRING,"Aspiration: ",
PANEL_VALUE,2,
PANEL_SHOW_MENU,TRUE,
PANEL_CHOICE_STRINGS,"1","2","3","4","5","6",0,
PANEL_DISPLAY_LEVEL,PANEL_CURRENT,
0) ;
difficulty_choice = panel_create_item(panel,PANEL_CYCLE,
PANEL_NOTIFY_PROC,difficulty_proc,
PANEL_LABEL_BOLD,TRUE,
PANEL_LABEL_STRING,"Difficulty: ",
PANEL_VALUE,0,
PANEL_SHOW_MENU,TRUE,
PANEL_CHOICE_STRINGS,"1","2","3","4",0,
PANEL_DISPLAY_LEVEL,PANEL_CURRENT,
0) ;
computer_plays_choice = panel_create_item(panel,PANEL_CYCLE,
PANEL_NOTIFY_PROC,computer_plays_proc,
PANEL_LABEL_BOLD,TRUE,
PANEL_LABEL_STRING,"Computer plays: ",
PANEL_VALUE,0,
PANEL_SHOW_MENU,TRUE,
PANEL_CHOICE_STRINGS,"black","white","both",0,
PANEL_DISPLAY_LEVEL,PANEL_CURRENT,
0) ;
remark_choice = panel_create_item(panel,PANEL_CYCLE,
PANEL_NOTIFY_PROC,remark_proc,
PANEL_LABEL_BOLD,TRUE,
PANEL_LABEL_STRING,"Remarks: ",
PANEL_VALUE,1,
PANEL_SHOW_MENU,TRUE,
PANEL_CHOICE_STRINGS,"off","on",0,
PANEL_DISPLAY_LEVEL,PANEL_CURRENT,
0) ;
remark_mes = panel_create_item(panel,PANEL_MESSAGE,
PANEL_LABEL_STRING," ",
0) ;
panel_mes = panel_create_item(panel,PANEL_MESSAGE,
PANEL_LABEL_STRING,"To move, use your left mouse button",
0) ;
score_mes = panel_create_item(panel,PANEL_MESSAGE,
PANEL_LABEL_STRING,"White: 2, Black: 2",
0) ;
}
/*ARGSUSED*/
static void
quit_proc(item,event)
Panel_item item ;
Event *event ;
{
window_done(base_frame) ;
}
static void
suggest_proc()
{
if (canvas_mode == white_start)
suggestion = makemove(board,WHITE,depth) ;
else suggestion = makemove(board,BLACK,depth) ;
suggest_x = ((suggestion & 7) + 1) * CELL_WIDTH - CELL_WIDTH / 2 ;
suggest_y = ((suggestion >> 3) + 1) * CELL_WIDTH - CELL_WIDTH / 2 ;
pw_vector(canvas_pw,suggest_x-5,suggest_y-5,
suggest_x+5,suggest_y+5,RSRC,0xff) ;
pw_vector(canvas_pw,suggest_x-5,suggest_y+5,
suggest_x+5,suggest_y-5,RSRC,0xff) ;
}
static void
draw_piece(player,x,y,rop)
int player,x,y,rop ;
{
switch (player)
{
case WHITE : pw_write(canvas_pw,x,y,32,32,rop,&white_icon_pr,0,0) ;
break ;
case BLACK : pw_write(canvas_pw,x,y,32,32,rop,&black_icon_pr,0,0) ;
}
}
static void
last_proc()
{
int flips,i,player,rop,x,y ;
player = (canvas_mode == white_start) ? BLACK : WHITE ;
for (flips = 0; flips < 4; flips++)
{
x = (last_move & 7)*CELL_WIDTH + PIECE_MARGIN ;
y = (last_move >> 3)*CELL_WIDTH + PIECE_MARGIN ;
rop = flips % 2 ? RSRC : RCLR ;
draw_piece(player,x,y,rop) ;
PAUSE(i) ;
}
}
/*ARGSUSED*/
static void
difficulty_proc(item,value,event)
Panel_item item ;
int value ;
Event *event ;
{
depth = value + INIT_DEPTH ;
}
/*ARGSUSED*/
static void
remark_proc(item,value,event)
Panel_item item ;
int value ;
Event *event ;
{
remark = value ;
if (remark) remark_msg("OK, I'll make remarks") ;
else remark_msg("OK, I'll shut up") ;
}
/*ARGSUSED*/
static void
aspiration_proc(item,value,event)
Panel_item item ;
int value ;
Event *event ;
{
aspire = value ;
}
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) ;
}
static void
update_board_image()
{
int flips,i,j,rop,x,y ;
if (suggestion != -1)
{
pw_vector(canvas_pw,suggest_x-5,suggest_y-5,
suggest_x+5,suggest_y+5,RCLR,0xff) ;
pw_vector(canvas_pw,suggest_x-5,suggest_y+5,
suggest_x+5,suggest_y-5,RCLR,0xff) ;
suggestion = -1 ;
}
for (flips = 0; flips < 4; flips++)
{
pw_batch_on(canvas_pw) ;
rop = flips % 2 ? RSRC : RCLR ;
FOR_BOARD(i)
{
if (board.SQUARE[i] != old_board.SQUARE[i])
{
x = (i & 7) * CELL_WIDTH + PIECE_MARGIN ;
y = (i >> 3) * CELL_WIDTH + PIECE_MARGIN ;
draw_piece(board.SQUARE[i],x,y,rop) ;
}
}
pw_batch_off(canvas_pw) ;
PAUSE(j) ;
}
score_msg(sprintf(line,"White: %2d, Black: %2d",
count(board,WHITE),count(board,BLACK))) ;
}
static void
canvas_init()
{
int x0 ;
pw_writebackground(canvas_pw,0,0,TOTAL_WIDTH+1,TOTAL_WIDTH+1,RSRC) ;
pw_batch_on(canvas_pw) ;
for (x0 = 0; x0 <= TOTAL_WIDTH; x0 += CELL_WIDTH)
{
pw_vector(canvas_pw,x0,0,x0,TOTAL_WIDTH,RSRC,0xff) ;
pw_vector(canvas_pw,0,x0,TOTAL_WIDTH,x0,RSRC,0xff) ;
}
pw_batch_off(canvas_pw) ;
update_board_image() ;
}
static void
animate_move(move)
int move ;
{
int x0,y0,x1,y1,x,y,dx,dy,ctr ;
static struct rect r = {0,0,TOTAL_WIDTH+1,TOTAL_WIDTH+1} ;
pw_lock(canvas_pw,&r) ;
dx = x1 = (move & 7) * CELL_WIDTH + PIECE_MARGIN ;
dy = y1 = (move >> 3) * CELL_WIDTH + PIECE_MARGIN ;
if (x1 > y1)
{
ctr = dx/2 ;
x = 0 ;
y = 0 ;
draw_piece(WHITE,x,y,RINV) ;
while (x < x1)
{
x0 = x ;
y0 = y ;
x += MOVE_DELTA ;
if ((ctr -= dy) < 0)
{
ctr += dx ;
y += MOVE_DELTA ;
}
draw_piece(WHITE,x,y,RINV) ;
draw_piece(WHITE,x0,y0,RINV) ;
}
draw_piece(WHITE,x,y,RINV) ;
}
else
{
ctr = dy/2 ;
x = 0 ;
y = 0 ;
draw_piece(WHITE,x,y,RINV) ;
while (y < y1)
{
x0 = x ;
y0 = y ;
y += MOVE_DELTA ;
if ((ctr -= dx) < 0)
{
ctr += dy ;
x += MOVE_DELTA ;
}
draw_piece(WHITE,x,y,RINV) ;
draw_piece(WHITE,x0,y0,RINV) ;
}
draw_piece(WHITE,x,y,RINV) ;
}
pw_unlock(canvas_pw) ;
}
static void
who_wins()
{
int cs,ps ;
ps = count(board,WHITE) ;
cs = count(board,BLACK) ;
if (ps > cs) score_msg(sprintf(line,"White wins %d-%d",ps,cs)) ;
else if (ps == cs) score_msg(sprintf(line,"A tie %d-%d",ps,cs)) ;
else score_msg(sprintf(line,"Black wins %d-%d",cs,ps)) ;
if (cretin_flag) remark_msg("*** CRETIN! ***") ;
else remark_msg("") ;
}
do_move(player,who)
int player ;
char who[3][9] ;
{
int taken ; /* Number of pieces flipped this go. */
taken = formfliplist(move,player) ;
update_board_image() ;
if (taken == 1)
panel_msg(sprintf(line,"%s took 1 piece",who[(int) play_mode])) ;
else panel_msg(sprintf(line,"%s took %d pieces",who[(int) play_mode],taken)) ;
}
formfliplist(move,player)
int move,player ;
{
int cnt,i,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) ;
cnt = count(board,player) ;
return(cnt - old_cnt - 1) ;
}
check(player,who,be)
int player ;
char who[3][9],be[3][4] ;
/* 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.
*/
{
if ((!count(board,BLACK)) || (!count(board,WHITE)) ||
((count(board,BLACK) + count(board,WHITE)) == 64))
{
who_wins() ;
canvas_mode = game_over ;
panel_msg("Game over") ;
return(FALSE) ;
}
if ((move = makemove(board,player,0)) == NOMOVE)
{
panel_msg(sprintf(line,"%s %s forced to pass",
who[(int) play_mode],be[(int) play_mode])) ;
if ((move = makemove(board,OPPONENT(player),0)) == NOMOVE)
{
who_wins() ;
canvas_mode = game_over ;
panel_msg("Game over") ;
}
return(FALSE) ;
}
return(TRUE) ;
}
think(player,who)
int player ;
char who[3][9] ;
{
window_set(canvas,WIN_CURSOR,hglass_cursor,0) ;
move = makemove(board,player,depth) ;
window_set(canvas,WIN_CURSOR,canvas_cursor,0) ;
animate_move(move) ;
do_move(player,who) ;
last_move = move ;
canvas_mode = (enum cmode) (OPPONENT(player) + 1) ;
}
move_and_check(player,who,be,opp_who,opp_be)
int player ;
char who[3][9],be[3][4],opp_who[3][9],opp_be[3][4] ;
{
do_move(player,who) ;
for (;;)
if (check(OPPONENT(player),opp_who,opp_be) == TRUE)
{
think(OPPONENT(player),opp_who) ;
if (check(player,who,be) == TRUE) break ;
if (canvas_mode == game_over) break ;
}
else
{
canvas_mode = (enum cmode) ((int) canvas_mode - 1) ;
return ;
}
}
do_action(event)
Event *event ;
{
int cx,cy ;
switch (event_id(event))
{
case LOC_MOVE :
case LOC_DRAG :
case LOC_TRAJECTORY :
draw_piece(next_player,piece_x,piece_y,RINV) ;
piece_x = event_x(event) - PIECE_RAD ;
piece_y = event_y(event) - PIECE_RAD ;
draw_piece(next_player,piece_x,piece_y,RINV) ;
break ;
case LOC_WINENTER :
case LOC_WINEXIT :
case LOC_RGNENTER :
case LOC_RGNEXIT :
case WIN_STOP : draw_piece(next_player,piece_x,piece_y,RINV) ;
canvas_mode = (enum cmode) ((int) canvas_mode - 1) ;
break ;
case MS_LEFT :
cursor_set(canvas_cursor,CURSOR_SHOW_CURSOR,TRUE,0) ;
window_set(canvas,WIN_CURSOR,canvas_cursor,0) ;
if (event_is_down(event))
{
draw_piece(next_player,piece_x,piece_y,RINV) ;
canvas_mode = (enum cmode) ((int) canvas_mode - 1) ;
}
else
{
draw_piece(next_player,piece_x,piece_y,RINV) ;
cx = (piece_x + PIECE_RAD) / CELL_WIDTH ;
cy = (piece_y + PIECE_RAD) / CELL_WIDTH ;
move = cy * BOARDSIZE + cx ;
if (legal(move,next_player,&board) == FALSE)
{
panel_msg("Invalid move") ;
canvas_mode = (enum cmode) ((int) canvas_mode - 1) ;
}
else
{
if (canvas_mode == white_moving)
move_and_check(WHITE,w_who,w_be,b_who,b_be) ;
else move_and_check(BLACK,b_who,b_be,w_who,w_be) ;
}
}
break ;
}
}
/*ARGSUSED*/
static void
canvas_proc(win,event,arg)
Canvas win ;
Event *event ;
caddr_t arg ;
{
switch (canvas_mode)
{
case white_start :
case black_start : next_player = (int) canvas_mode - 1 ;
if (event_id(event) == MS_LEFT && event_is_down(event))
{
cursor_set(canvas_cursor,CURSOR_SHOW_CURSOR,FALSE,0) ;
window_set(canvas,WIN_CURSOR,canvas_cursor,0) ;
piece_x = event_x(event) - PIECE_RAD ;
piece_y = event_y(event) - PIECE_RAD ;
draw_piece(next_player,piece_x,piece_y,RINV) ;
canvas_mode = (enum cmode) ((int) canvas_mode + 1) ;
}
break ;
case white_moving :
case black_moving : do_action(event) ;
break ;
case game_over : panel_msg("Game over") ;
break ;
}
}
/*ARGSUSED*/
static void
computer_plays_proc(item,value,event)
Panel_item item ;
int value ;
Event *event ;
{
int old_remark ;
switch (value)
{
case 0 : play_mode = play_black ;
if (canvas_mode != game_over)
if (check(BLACK,b_who,b_be) == TRUE)
think(BLACK,b_who) ;
break ;
case 1 : play_mode = play_white ;
if (canvas_mode != game_over)
if (check(WHITE,w_who,w_be) == TRUE)
think(WHITE,w_who) ;
break ;
case 2 : if (play_mode != play_both)
{
play_mode = play_both ;
old_remark = remark ;
remark = 0 ;
while (play_mode == play_both && canvas_mode != game_over)
{
if (canvas_mode == white_start)
{
for (;;)
if (check(WHITE,w_who,w_be) == TRUE)
{
think(WHITE,w_who) ;
canvas_mode = black_start ;
if (check(BLACK,b_who,b_be) == TRUE) break ;
if (canvas_mode == game_over) break ;
canvas_mode = white_start ;
}
}
else
{
for (;;)
if (check(BLACK,b_who,b_be) == TRUE)
{
think(BLACK,b_who) ;
canvas_mode = white_start ;
if (check(WHITE,w_who,w_be) == TRUE) break ;
if (canvas_mode == game_over) break ;
canvas_mode = black_start ;
}
}
notify_dispatch() ;
}
}
remark = old_remark ;
break ;
}
}
static void
new_game_proc()
{
initboard() ;
play_mode = play_black ;
panel_set_value(computer_plays_choice,0) ;
canvas_mode = white_start ;
last_move = -1 ;
canvas_init() ;
remark_msg("") ;
panel_msg("To move, use your left mouse button") ;
}