DataMuseum.dk

Presents historical artifacts from the history of:

DKUUG/EUUG Conference tapes

This is an automatic "excavation" of a thematic subset of
artifacts from Datamuseum.dk's BitArchive.

See our Wiki for more about DKUUG/EUUG Conference tapes

Excavated with: AutoArchaeologist - Free & Open Source Software.


top - metrics - download
Index: T o

⟦a8df9b651⟧ TextFile

    Length: 18018 (0x4662)
    Types: TextFile
    Names: »otool.c«

Derivation

└─⟦b20c6495f⟧ Bits:30007238 EUUGD18: Wien-båndet, efterår 1987
    └─⟦this⟧ »EUUGD18/Sun/Othello/otool.c« 

TextFile

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