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