|
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") ; }