예제 #1
0
InputCommand()

/*
   Process the users command. If easy mode is OFF (the computer is 
   thinking on opponents time) and the program is out of book, then make 
   the 'hint' move on the board and call SelectMove() to find a response. 
   The user terminates the search by entering ^C (quit siqnal) before 
   entering a command. If the opponent does not make the hint move, then 
   set Sdepth to zero. 
*/

{
int i;
short ok,tmp;
long cnt,rate,t1,t2;
unsigned short mv;
char s[80];

  ok = quit = false;
  player = opponent;
  ft = 0;
  if (hint > 0 && !easy && Book == NULL)
    {
      fflush(stdout);
      time0 = time((long *)0);
      algbr(hint>>8,hint & 0xFF,false);
      strcpy(s,mvstr1);
      tmp = epsquare;
      if (VerifyMove(s,1,&mv))
        {
          SelectMove(computer,2);
          VerifyMove(mvstr1,2,&mv);
          if (Sdepth > 0) Sdepth--;
        }
      ft = time((long *)0) - time0;
      epsquare = tmp;
    }
예제 #2
0
void coords_to_pgn(struct pgn_ply_node* ply){
    int pos = 0,i,j;
    unsigned short moving_piece = board[locn[ply->row_from][ply->column_from]];
    char unambiguous_position;
    bool found = false;
    char alg_move[5];
    char move_buffer[10];
    short move;
    if (moving_piece == king){
        /* check castling */
        if (ply->column_from == 4 && ply->column_to == 6){
            /* castling kingside */
            rb->strcpy(ply->pgn_text,"O-O");
            ply->castle = true;
        } else if (ply->column_from == 4 && ply->column_to == 2){
            /* castling queenside */
            rb->strcpy(ply->pgn_text,"O-O-O");
        } else {
            if (board[locn[ply->row_to][ply->column_to]] != no_piece){
                rb->snprintf(ply->pgn_text,10,"Kx%c%c",'a'+ply->column_to,
                                   '1'+ply->row_to);
            } else {
                rb->snprintf(ply->pgn_text,10,"K%c%c",'a'+ply->column_to,
                                   '1'+ply->row_to);
            }
        }
    } else if (moving_piece == pawn){
        if (ply->column_from != ply->column_to){
            /* check enpassant */
            if (board[locn[ply->row_to][ply->column_to]] == no_piece){
                ply->enpassant = true;
            }
            /* check promotions when taking a piece */
            if (ply->row_to == 0 || ply->row_to == 7) {
                ply->promotion = true;
                ply->promotion_piece = queen;
                rb->snprintf(ply->pgn_text,10,"%cx%c%c=D", 'a'+ply->column_from,
                                   'a'+ply->column_to,'1'+ply->row_to);
            } else {
                rb->snprintf(ply->pgn_text,10,"%cx%c%c", 'a'+ply->column_from,
                                   'a'+ply->column_to,'1'+ply->row_to);
            }
        } else {
            /* check promotions when not taking a piece */
            if (ply->row_to == 0 || ply->row_to == 7) {
                ply->promotion = true;
                ply->promotion_piece = queen;
                rb->snprintf(ply->pgn_text,10,"%c%c=D", 'a'+ply->column_to,
                                   '1'+ply->row_to);
            } else {
                rb->snprintf(ply->pgn_text,10,"%c%c", 'a'+ply->column_to,
                                   '1'+ply->row_to);
            }
        }
    } else {
        /* verify ambiguous moves for the different kinds of pieces */
        unambiguous_position = '\0';
        if (moving_piece == knight){
            for (i=0;i<8;i++){
                if (ply->row_to + kn_offs[i][0] >= 0 && ply->row_to + kn_offs[i][0] <= 7
                    && ply->column_to + kn_offs[i][1] >= 0 && ply->column_to + kn_offs[i][1] <= 7
                    && board[locn[ply->row_to + kn_offs[i][0]][ply->column_to + kn_offs[i][1]]] == knight
                    && color[locn[ply->row_to + kn_offs[i][0]][ply->column_to + kn_offs[i][1]]] == ply->player
                    && (ply->row_to + kn_offs[i][0] != ply->row_from 
                        || ply->column_to + kn_offs[i][1] != ply->column_from)){
                    if (ply->row_to + kn_offs[i][0] != ply->row_from){
                        unambiguous_position = '1' + ply->row_from;
                    } else {
                        unambiguous_position = 'a' + ply->column_from;
                    }
                    break;
                }
            }
        }
        if (moving_piece == rook || moving_piece == queen){
            found = false;
            for (i=0;i<4;i++){
                j=1;
                while (ply->row_to+(j*rk_offs[i][0]) >= 0 && ply->row_to+(j*rk_offs[i][0]) <= 7 &&
                       ply->column_to+(j*rk_offs[i][1]) >= 0 && ply->column_to+(j*rk_offs[i][1]) <= 7){
                    if (board[locn[ply->row_to+(j*rk_offs[i][0])][ply->column_to+(j*rk_offs[i][1])]] != no_piece) {
                        if (board[locn[ply->row_to+(j*rk_offs[i][0])][ply->column_to+(j*rk_offs[i][1])]] == moving_piece &&
                            color[locn[ply->row_to+(j*rk_offs[i][0])][ply->column_to+(j*rk_offs[i][1])]] == ply->player &&
                            (ply->row_to+(j*rk_offs[i][0]) != ply->row_from
                             || ply->column_to+(j*rk_offs[i][1]) != ply->column_from)) {
                            if (ply->row_to+(j*rk_offs[i][0]) != ply->row_from){
                                unambiguous_position = '1' + ply->row_from;
                            } else {
                                unambiguous_position = 'a' + ply->column_from;
                            }
                            found = true;
                        }
                        break;
                    }
                    j++;
                }
                if (found) {
                    break;
                }
            }
        }
        if (moving_piece == bishop || (moving_piece == queen && !found)){
            for (i=0;i<4;i++){
                j=1;
                while (ply->row_to+(j*bp_offs[i][0]) >= 0 && ply->row_to+(j*bp_offs[i][0]) <= 7 &&
                       ply->column_to+(j*bp_offs[i][1]) >= 0 && ply->column_to+(j*bp_offs[i][1]) <= 7){
                    if (board[locn[ply->row_to+(j*bp_offs[i][0])][ply->column_to+(j*bp_offs[i][1])]] != no_piece) {
                        if (board[locn[ply->row_to+(j*bp_offs[i][0])][ply->column_to+(j*bp_offs[i][1])]] == moving_piece &&
                            color[locn[ply->row_to+(j*bp_offs[i][0])][ply->column_to+(j*bp_offs[i][1])]] == ply->player &&
                            (ply->row_to+(j*bp_offs[i][0]) != ply->row_from
                             || ply->column_to+(j*bp_offs[i][1]) != ply->column_from)) {
                            if (ply->row_to+(j*bp_offs[i][0]) != ply->row_from){
                                unambiguous_position = '1' + ply->row_from;
                            } else {
                                unambiguous_position = 'a' + ply->column_from;
                            }
                            found = true;
                        }
                        break;
                    }
                    j++;
                }
                if (found) {
                    break;
                }
            }
        }
        /* generate the first portion of the PGN text
         * always as white so all uppercase, black/white considerations
         * will be useful for FEN notation but not in this case
         */
        if (unambiguous_position == '\0'){
            if (board[locn[ply->row_to][ply->column_to]] != no_piece){
                rb->snprintf(ply->pgn_text,10,"%cx%c%c",
                                   pgn_from_piece(moving_piece,white) ,
                                   'a'+ply->column_to, '1'+ply->row_to);
            } else {
                rb->snprintf(ply->pgn_text,10,"%c%c%c",
                                   pgn_from_piece(moving_piece,white) ,
                                   'a'+ply->column_to, '1'+ply->row_to);
            }
        } else {
            if (board[locn[ply->row_to][ply->column_to]] != no_piece){
                rb->snprintf(ply->pgn_text,10,"%c%cx%c%c",
                                   pgn_from_piece(moving_piece,white) ,
                                   unambiguous_position, 'a'+ply->column_to,
                                   '1'+ply->row_to);
            } else {
                rb->snprintf(ply->pgn_text,10,"%c%c%c%c",
                                   pgn_from_piece(moving_piece,white) ,
                                   unambiguous_position, 'a'+ply->column_to,
                                   '1'+ply->row_to);
            }
        }
    }
    /* update the board */
    rb->snprintf(alg_move,5,"%c%c%c%c",'a' + ply->column_from, '1' + ply->row_from,
                'a' + ply->column_to, '1' + ply->row_to);
    /* The function returns false if the move is invalid, but since we're
     * replaying the game, that should not be posible
     */
    VerifyMove (ply->player, alg_move , 0 , &move, move_buffer );

    /* add check/mate indicators */
    for (pos=0;ply->pgn_text[pos] != '\0';pos++);
    if (ply->checkmate) {
        ply->pgn_text[pos] = '#'; pos++;
        ply->pgn_text[pos] = '\0'; pos++;
    } else if (move_buffer[4] == '+'){
        ply->pgn_text[pos] = '+'; pos++;
        ply->pgn_text[pos] = '\0'; pos++;
    }
}
예제 #3
0
/*
 *******************************************************************************
 *                                                                             *
 *   Ponder() is the driver for "pondering" (thinking on the opponent's time.) *
 *   its operation is simple:  Find a predicted move by (a) taking the second  *
 *   move from the principal variation, or (b) call lookup to see if it finds  *
 *   a suggested move from the transposition table.  Then, make this move and  *
 *   do a search from the resulting position.  While pondering, one of three   *
 *   things can happen:  (1) A move is entered, and it matches the predicted   *
 *   move.  We then switch from pondering to thinking and search as normal;    *
 *   (2) A move is entered, but it does not match the predicted move.  We then *
 *   abort the search, unmake the pondered move, and then restart with the     *
 *   move entered.  (3) A command is entered.  If it is a simple command, it   *
 *   can be done without aborting the search or losing time.  If not, we abort *
 *   the search, execute the command, and then attempt to restart pondering if *
 *   the command didn't make that impossible.                                  *
 *                                                                             *
 *******************************************************************************
 */
int Ponder(int wtm) {
  TREE *const tree = block[0];
  int dalpha = -999999, dbeta = 999999, i;
  unsigned *n_ponder_moves, *mv;
  int save_move_number, tlom, value;

/*
 ************************************************************
 *                                                          *
 *  First, let's check to see if pondering is allowed, or   *
 *  if we should avoid pondering on this move since it is   *
 *  the first move of a game, or if the game is over, or    *
 *  "force" mode is active, or there is input in the queue  *
 *  that needs to be read and processed.                    *
 *                                                          *
 ************************************************************
 */
  if (!ponder || force || over || CheckInput())
    return 0;
  save_move_number = move_number;
/*
 ************************************************************
 *                                                          *
 *  Check the ponder move for legality.  If it is not a     *
 *  legal move, we have to take action to find something to *
 *  ponder.                                                 *
 *                                                          *
 ************************************************************
 */
  strcpy(ponder_text, "none");
  if (ponder_move) {
    if (!VerifyMove(tree, 1, wtm, ponder_move)) {
      ponder_move = 0;
      Print(4095, "ERROR.  ponder_move is illegal (1).\n");
      Print(4095, "ERROR.  PV pathl=%d\n", last_pv.pathl);
      Print(4095, "ERROR.  move=%d  %x\n", ponder_move, ponder_move);
    }
  }
/*
 ************************************************************
 *                                                          *
 *  First attempt, do a hash probe.  However, since a hash  *
 *  collision is remotely possible, we still need to verify *
 *  that the transposition/refutation best move is actually *
 *  legal.                                                  *
 *                                                          *
 ************************************************************
 */
  if (!ponder_move) {
    HashProbe(tree, 0, 0, wtm, dalpha, dbeta, &value);
    if (tree->hash_move[0])
      ponder_move = tree->hash_move[0];
    if (ponder_move) {
      if (!VerifyMove(tree, 1, wtm, ponder_move)) {
        Print(4095, "ERROR.  ponder_move is illegal (2).\n");
        Print(4095, "ERROR.  move=%d  %x\n", ponder_move, ponder_move);
        ponder_move = 0;
      }
    }
  }
/*
 ************************************************************
 *                                                          *
 *  Second attempt.  If that didn't work, then we try what  *
 *  I call a "puzzling" search.  Which is simply a shorter  *
 *  time-limit search for the other side, to find something *
 *  to ponder.                                              *
 *                                                          *
 ************************************************************
 */
  if (!ponder_move) {
    TimeSet(puzzle);
    if (time_limit < 20)
      return 0;
    puzzling = 1;
    tree->status[1] = tree->status[0];
    Print(32, "              puzzling over a move to ponder.\n");
    last_pv.pathl = 0;
    last_pv.pathd = 0;
    for (i = 0; i < MAXPLY; i++) {
      tree->killers[i].move1 = 0;
      tree->killers[i].move2 = 0;
    }
    Iterate(wtm, puzzle, 0);
    for (i = 0; i < MAXPLY; i++) {
      tree->killers[i].move1 = 0;
      tree->killers[i].move2 = 0;
    }
    puzzling = 0;
    if (tree->pv[0].pathl)
      ponder_move = tree->pv[0].path[1];
    if (!ponder_move)
      return 0;
    for (i = 1; i < (int) tree->pv[0].pathl; i++)
      last_pv.path[i] = tree->pv[0].path[i + 1];
    last_pv.pathl = tree->pv[0].pathl - 1;
    last_pv.pathd = 0;
    if (!VerifyMove(tree, 1, wtm, ponder_move)) {
      ponder_move = 0;
      Print(4095, "ERROR.  ponder_move is illegal (3).\n");
      Print(4095, "ERROR.  PV pathl=%d\n", last_pv.pathl);
      return 0;
    }
  }
/*
 ************************************************************
 *                                                          *
 *  Display the move we are going to "ponder".              *
 *                                                          *
 ************************************************************
 */
  if (wtm)
    Print(32, "White(%d): %s [pondering]\n", move_number, OutputMove(tree, 0,
            wtm, ponder_move));
  else
    Print(32, "Black(%d): %s [pondering]\n", move_number, OutputMove(tree, 0,
            wtm, ponder_move));
  sprintf(ponder_text, "%s", OutputMove(tree, 0, wtm, ponder_move));
  if (post)
    printf("Hint: %s\n", ponder_text);
/*
 ************************************************************
 *                                                          *
 *  Set the ponder move list and eliminate illegal moves.   *
 *  This list is used to test the move entered while we are *
 *  pondering, since we need a move list for the input      *
 *  screening process.                                      *
 *                                                          *
 ************************************************************
 */
  n_ponder_moves = GenerateCaptures(tree, 0, wtm, ponder_moves);
  num_ponder_moves =
      GenerateNoncaptures(tree, 0, wtm, n_ponder_moves) - ponder_moves;
  for (mv = ponder_moves; mv < ponder_moves + num_ponder_moves; mv++) {
    MakeMove(tree, 0, wtm, *mv);
    if (Check(wtm)) {
      UnmakeMove(tree, 0, wtm, *mv);
      *mv = 0;
    } else
      UnmakeMove(tree, 0, wtm, *mv);
  }
/*
 ************************************************************
 *                                                          *
 *  Now, perform an iterated search, but with the special   *
 *  "pondering" flag set which changes the time controls    *
 *  since there is no need to stop searching until the      *
 *  opponent makes a move.                                  *
 *                                                          *
 ************************************************************
 */
  MakeMove(tree, 0, wtm, ponder_move);
  tree->curmv[0] = ponder_move;
  tree->rep_list[++rep_index] = HashKey;
  tlom = last_opponent_move;
  last_opponent_move = ponder_move;
  if (kibitz)
    strcpy(kibitz_text, "n/a");
  thinking = 0;
  pondering = 1;
  if (!wtm)
    move_number++;
  ponder_value = Iterate(Flip(wtm), think, 0);
  rep_index--;
  move_number = save_move_number;
  pondering = 0;
  thinking = 0;
  last_opponent_move = tlom;
  UnmakeMove(tree, 0, wtm, ponder_move);
/*
 ************************************************************
 *                                                          *
 *  Search completed. the possible return values are:       *
 *                                                          *
 *  (0) No pondering was done, period.                      *
 *                                                          *
 *  (1) Pondering was done, opponent made the predicted     *
 *      move, and we searched until time ran out in a       *
 *      normal manner.                                      *
 *                                                          *
 *  (2) Pondering was done, but the ponder search           *
 *      terminated due to either finding a mate, or the     *
 *      maximum search depth was reached.  The result of    *
 *      this ponder search are valid, but only if the       *
 *      opponent makes the correct (predicted) move.        *
 *                                                          *
 *  (3) Pondering was done, but the opponent either made a  *
 *      different move, or entered a command that has to    *
 *      interrupt the pondering search before the command   *
 *      (or move) can be processed.  This forces Main() to  *
 *      avoid reading in a move/command since one has been  *
 *      read into the command buffer already.               *
 *                                                          *
 ************************************************************
 */
  if (input_status == 1)
    return 1;
  if (input_status == 2)
    return 3;
  return 2;
}