Subversion Repositories Games.Chess Giants

Rev

Rev 33 | Go to most recent revision | Details | Compare with Previous | Last modification | View Log | RSS feed

Rev Author Line No. Line
33 pmbaty 1
#include "chess.h"
2
#include "data.h"
3
/* last modified 02/23/14 */
4
/*
5
 *******************************************************************************
6
 *                                                                             *
7
 *   Ponder() is the driver for "pondering" (thinking on the opponent's time.) *
8
 *   its operation is simple:  Find a predicted move by (a) taking the second  *
9
 *   move from the principal variation, or (b) call lookup to see if it finds  *
10
 *   a suggested move from the transposition table.  Then, make this move and  *
11
 *   do a search from the resulting position.  While pondering, one of three   *
12
 *   things can happen:  (1) A move is entered, and it matches the predicted   *
13
 *   move.  We then switch from pondering to thinking and search as normal;    *
14
 *   (2) A move is entered, but it does not match the predicted move.  We then *
108 pmbaty 15
 *   abort the search, unmake the pondered move, and then restart with the     *
16
 *   move entered.  (3) A command is entered.  If it is a simple command, it   *
17
 *   can be done without aborting the search or losing time.  If not, we abort *
18
 *   the search, execute the command, and then attempt to restart pondering if *
19
 *   the command didn't make that impossible.                                  *
33 pmbaty 20
 *                                                                             *
21
 *******************************************************************************
22
 */
23
int Ponder(int wtm) {
108 pmbaty 24
  TREE *const tree = block[0];
25
  int dalpha = -999999, dbeta = 999999, i;
26
  unsigned *n_ponder_moves, *mv;
33 pmbaty 27
  int save_move_number, tlom, value;
28
 
29
/*
30
 ************************************************************
31
 *                                                          *
32
 *  First, let's check to see if pondering is allowed, or   *
33
 *  if we should avoid pondering on this move since it is   *
34
 *  the first move of a game, or if the game is over, or    *
35
 *  "force" mode is active, or there is input in the queue  *
36
 *  that needs to be read and processed.                    *
37
 *                                                          *
38
 ************************************************************
39
 */
40
  if (!ponder || force || over || CheckInput())
41
    return 0;
42
  save_move_number = move_number;
43
/*
44
 ************************************************************
45
 *                                                          *
46
 *  Check the ponder move for legality.  If it is not a     *
47
 *  legal move, we have to take action to find something to *
48
 *  ponder.                                                 *
49
 *                                                          *
50
 ************************************************************
51
 */
108 pmbaty 52
  strcpy(ponder_text, "none");
33 pmbaty 53
  if (ponder_move) {
54
    if (!VerifyMove(tree, 1, wtm, ponder_move)) {
55
      ponder_move = 0;
56
      Print(4095, "ERROR.  ponder_move is illegal (1).\n");
57
      Print(4095, "ERROR.  PV pathl=%d\n", last_pv.pathl);
58
      Print(4095, "ERROR.  move=%d  %x\n", ponder_move, ponder_move);
59
    }
60
  }
61
/*
62
 ************************************************************
63
 *                                                          *
64
 *  First attempt, do a hash probe.  However, since a hash  *
65
 *  collision is remotely possible, we still need to verify *
66
 *  that the transposition/refutation best move is actually *
67
 *  legal.                                                  *
68
 *                                                          *
69
 ************************************************************
70
 */
71
  if (!ponder_move) {
108 pmbaty 72
    HashProbe(tree, 0, 0, wtm, dalpha, dbeta, &value);
33 pmbaty 73
    if (tree->hash_move[0])
74
      ponder_move = tree->hash_move[0];
75
    if (ponder_move) {
76
      if (!VerifyMove(tree, 1, wtm, ponder_move)) {
77
        Print(4095, "ERROR.  ponder_move is illegal (2).\n");
78
        Print(4095, "ERROR.  move=%d  %x\n", ponder_move, ponder_move);
79
        ponder_move = 0;
80
      }
81
    }
82
  }
83
/*
84
 ************************************************************
85
 *                                                          *
86
 *  Second attempt.  If that didn't work, then we try what  *
87
 *  I call a "puzzling" search.  Which is simply a shorter  *
88
 *  time-limit search for the other side, to find something *
89
 *  to ponder.                                              *
90
 *                                                          *
91
 ************************************************************
92
 */
93
  if (!ponder_move) {
94
    TimeSet(puzzle);
95
    if (time_limit < 20)
96
      return 0;
97
    puzzling = 1;
98
    tree->status[1] = tree->status[0];
108 pmbaty 99
    Print(32, "              puzzling over a move to ponder.\n");
33 pmbaty 100
    last_pv.pathl = 0;
101
    last_pv.pathd = 0;
102
    for (i = 0; i < MAXPLY; i++) {
103
      tree->killers[i].move1 = 0;
104
      tree->killers[i].move2 = 0;
105
    }
108 pmbaty 106
    Iterate(wtm, puzzle, 0);
33 pmbaty 107
    for (i = 0; i < MAXPLY; i++) {
108
      tree->killers[i].move1 = 0;
109
      tree->killers[i].move2 = 0;
110
    }
111
    puzzling = 0;
112
    if (tree->pv[0].pathl)
113
      ponder_move = tree->pv[0].path[1];
114
    if (!ponder_move)
115
      return 0;
116
    for (i = 1; i < (int) tree->pv[0].pathl; i++)
117
      last_pv.path[i] = tree->pv[0].path[i + 1];
118
    last_pv.pathl = tree->pv[0].pathl - 1;
119
    last_pv.pathd = 0;
120
    if (!VerifyMove(tree, 1, wtm, ponder_move)) {
121
      ponder_move = 0;
122
      Print(4095, "ERROR.  ponder_move is illegal (3).\n");
123
      Print(4095, "ERROR.  PV pathl=%d\n", last_pv.pathl);
124
      return 0;
125
    }
126
  }
127
/*
128
 ************************************************************
129
 *                                                          *
130
 *  Display the move we are going to "ponder".              *
131
 *                                                          *
132
 ************************************************************
133
 */
134
  if (wtm)
108 pmbaty 135
    Print(32, "White(%d): %s [pondering]\n", move_number, OutputMove(tree, 0,
136
            wtm, ponder_move));
33 pmbaty 137
  else
108 pmbaty 138
    Print(32, "Black(%d): %s [pondering]\n", move_number, OutputMove(tree, 0,
139
            wtm, ponder_move));
140
  sprintf(ponder_text, "%s", OutputMove(tree, 0, wtm, ponder_move));
33 pmbaty 141
  if (post)
108 pmbaty 142
    printf("Hint: %s\n", ponder_text);
33 pmbaty 143
/*
144
 ************************************************************
145
 *                                                          *
146
 *  Set the ponder move list and eliminate illegal moves.   *
147
 *  This list is used to test the move entered while we are *
148
 *  pondering, since we need a move list for the input      *
149
 *  screening process.                                      *
150
 *                                                          *
151
 ************************************************************
152
 */
153
  n_ponder_moves = GenerateCaptures(tree, 0, wtm, ponder_moves);
154
  num_ponder_moves =
155
      GenerateNoncaptures(tree, 0, wtm, n_ponder_moves) - ponder_moves;
156
  for (mv = ponder_moves; mv < ponder_moves + num_ponder_moves; mv++) {
108 pmbaty 157
    MakeMove(tree, 0, wtm, *mv);
33 pmbaty 158
    if (Check(wtm)) {
108 pmbaty 159
      UnmakeMove(tree, 0, wtm, *mv);
33 pmbaty 160
      *mv = 0;
161
    } else
108 pmbaty 162
      UnmakeMove(tree, 0, wtm, *mv);
33 pmbaty 163
  }
164
/*
165
 ************************************************************
166
 *                                                          *
167
 *  Now, perform an iterated search, but with the special   *
168
 *  "pondering" flag set which changes the time controls    *
169
 *  since there is no need to stop searching until the      *
170
 *  opponent makes a move.                                  *
171
 *                                                          *
172
 ************************************************************
173
 */
108 pmbaty 174
  MakeMove(tree, 0, wtm, ponder_move);
175
  tree->curmv[0] = ponder_move;
176
  tree->rep_list[++rep_index] = HashKey;
33 pmbaty 177
  tlom = last_opponent_move;
178
  last_opponent_move = ponder_move;
179
  if (kibitz)
108 pmbaty 180
    strcpy(kibitz_text, "n/a");
33 pmbaty 181
  thinking = 0;
182
  pondering = 1;
183
  if (!wtm)
184
    move_number++;
185
  ponder_value = Iterate(Flip(wtm), think, 0);
108 pmbaty 186
  rep_index--;
33 pmbaty 187
  move_number = save_move_number;
188
  pondering = 0;
189
  thinking = 0;
190
  last_opponent_move = tlom;
108 pmbaty 191
  UnmakeMove(tree, 0, wtm, ponder_move);
33 pmbaty 192
/*
193
 ************************************************************
194
 *                                                          *
195
 *  Search completed. the possible return values are:       *
196
 *                                                          *
197
 *  (0) No pondering was done, period.                      *
198
 *                                                          *
199
 *  (1) Pondering was done, opponent made the predicted     *
200
 *      move, and we searched until time ran out in a       *
201
 *      normal manner.                                      *
202
 *                                                          *
203
 *  (2) Pondering was done, but the ponder search           *
204
 *      terminated due to either finding a mate, or the     *
205
 *      maximum search depth was reached.  The result of    *
206
 *      this ponder search are valid, but only if the       *
207
 *      opponent makes the correct (predicted) move.        *
208
 *                                                          *
108 pmbaty 209
 *  (3) Pondering was done, but the opponent either made a  *
210
 *      different move, or entered a command that has to    *
33 pmbaty 211
 *      interrupt the pondering search before the command   *
212
 *      (or move) can be processed.  This forces Main() to  *
213
 *      avoid reading in a move/command since one has been  *
214
 *      read into the command buffer already.               *
215
 *                                                          *
216
 ************************************************************
217
 */
218
  if (input_status == 1)
219
    return 1;
220
  if (input_status == 2)
221
    return 3;
222
  return 2;
223
}