/*LINTLIBRARY*/

/*  @(#)procs.c 1.5 90/04/09
 *
 *  Procedures associated with the othello game panel items.
 *
 *  Original SunView version by Ed Falk - Sun Microsystems Inc.
 *
 *  Rewritten for independent use by
 *          Rich Burridge, Sun Microsystems, Australia
 *
 *  Copyright (c) Ed Falk & Rich Burridge - Sun Microsystems.
 *                                          All rights reserved.
 *
 *  Permission is given to distribute these sources, as long as the
 *  introductory messages are not removed, and no monies are exchanged.
 *
 *  No responsibility is taken for any errors on inaccuracies inherent
 *  either to the comments or the code of this program, but if reported
 *  to me, then an attempt will be made to fix them.
 */

#include "color.h"
#include "othello.h"
#include "extern.h"


computer_plays()
{
  switch (next_setting(COMPUTER_PLAYS, comp_values))
    {
      case 0 : if (play_mode == PLAY_BLACK) return ;
               play_mode = PLAY_BLACK ;
               if (cmode != GAME_OVER)
                 if (check(BLACK, b_who, b_be) == TRUE)
                   think(BLACK, b_who) ;
               break ;

      case 1 : if (play_mode == PLAY_WHITE) return ;
               play_mode = PLAY_WHITE ;
               if (cmode != GAME_OVER)
                 if (check(WHITE, w_who, w_be) == TRUE)
                   think(WHITE, w_who) ;
    }
}


difficulty()
{
  depth = next_setting(DIFFICULTY, diff_values) + INIT_DEPTH ;
}


do_aspiration()
{
  aspire = next_setting(ASPIRATION, asp_values) ;
}


do_remark()
{
  remark = next_setting(REMARK, rem_values) ;
  if (remark) message(REMARK_MES, "Okay, I'll make remarks") ;
  else message(REMARK_MES, "Okay, no more remarks from me") ;
}


do_selection(state)
int state ;
{
  int cx, cy ;

  set_cursor(CANVASCUR) ;
  if (state == LEFT_DOWN)
    {
      draw_piece(next_player, piece_x, piece_y, RINV) ;
      cmode = (enum cantype) ((int) cmode - 1) ;
    }
  else
    {
      draw_piece(next_player, piece_x, piece_y, RINV) ;
      cx = (piece_x + PIECE_RAD) / CELL_SIZE ;
      cy = ((piece_y - CY) + PIECE_RAD) / CELL_SIZE ;
      move = cy * BOARD_SIZE + cx ;
      make_move() ;
    }
}


done()
{
  iconic = 1 ;
  close_frame() ;
}


last()
{
  enum optype rop ;
  int flips, player, x, y ;

  if (last_move == -1) return ;        /* No last move. */
  player = board.square[last_move] ;
  for (flips = 0; flips < 4; flips++)
    {
      get_xy(last_move, &x, &y) ;
      rop = flips % 2 ? RSRC : RCLR ;
      draw_piece(player, x, CY+y, rop) ;
      PAUSE ;
    }
}


make_move()
{
  if (legal(move, next_player, &board) == FALSE)
    {
      message(PANEL_MES, "Invalid move") ;
      cmode = (enum cantype) ((int) cmode - 1) ;
    }
  else
    {
      if (cmode == 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) ;
    }
}


new_game()
{
  initboard() ;
  play_mode = PLAY_WHITE ;
  items[(int) COMPUTER_PLAYS].value = 0 ;
  cmode = BLACK_START ;
  last_move = -1 ;
  init_canvas() ;
  message(REMARK_MES, "") ;
  message(PANEL_MES, "To move, use your left mouse button") ;
  draw_button(NEW_GAME_BUT, C_LGREY, BUT_NORMAL) ;
}


next_setting(item, choices)
enum panel_type item ;
char *choices[] ;
{
  switch (direction)
    {
      case INCREMENT : if (choices[++item_value] != NULL)
                         items[(int) item].value++ ;
                       else items[(int) item].value = item_value = 0 ;
                       break ;
      case DECREMENT : if (--item_value == -1)
                         {
                           while (choices[++item_value] != NULL) ;
                           item_value-- ;
                           items[(int) item].value = item_value ;
                         }
                       else items[(int) item].value-- ;
                       break ;
      case NONE      : /* Handled elsewhere. */ ;
    }
  set_cycle(item, choices[item_value]) ;
  return(items[(int) item].value) ;
}


quit()
{
  destroy_frame() ;
  exit(0) ;
}


suggest()
{
  if (cmode == GAME_OVER) return ;
  if (cmode == WHITE_START) suggestion = makemove(&board, WHITE, depth) ;
  else suggestion = makemove(&board, BLACK, depth) ;
  suggest_x = BBORDER + ((suggestion & 7) + 1) * CELL_SIZE - CELL_SIZE / 2 ;
  suggest_y = BBORDER + ((suggestion >> 3) + 1) * CELL_SIZE - CELL_SIZE / 2 ;
  draw_line(suggest_x-5, CY+suggest_y-5,
            suggest_x+5, CY+suggest_y+5, RSRC, C_BLACK) ;
  draw_line(suggest_x-5, CY+suggest_y+5,
            suggest_x+5, CY+suggest_y-5, RSRC, C_BLACK) ;
}


undo()
{
  int i, n, x, y ;

  n = 61 - board.moves_left ;
  if (n >= 3)
    {
      FOR_BOARD(i) board.square[i] = moves[n].square[i] ;
      board.moves_left = moves[n].moves_left ;
      FOR_BOARD(i) old_board.square[i] = moves[n-1].square[i] ;
      old_board.moves_left = moves[n-1].moves_left ;
      FOR_BOARD(i)
        {
          get_xy(i, &x, &y) ;
          if (board.square[i] == FREE)
            color_area(x, CY+y, PSIZE, PSIZE, (iscolor) ? C_LBROWN : C_WHITE) ;
          else draw_piece(board.square[i], x, CY+y, RSRC) ;
        }
    }
  else message(PANEL_MES, "No moves to undo.") ;
}
