Rev 33 | Rev 154 | 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 | #include "epdglue.h" |
||
| 108 | pmbaty | 4 | /* last modified 04/21/15 */ |
| 33 | pmbaty | 5 | /* |
| 6 | ******************************************************************************* |
||
| 7 | * * |
||
| 8 | * RootMoveList() is used to set up the ply one move list. It is a more * |
||
| 9 | * accurate ordering of the move list than that done for plies deeper than * |
||
| 10 | * one. Briefly, Quiesce() is used to obtain the positional score plus the * |
||
| 11 | * expected gain/loss for pieces that can be captured. * |
||
| 12 | * * |
||
| 13 | ******************************************************************************* |
||
| 14 | */ |
||
| 15 | void RootMoveList(int wtm) { |
||
| 16 | TREE *const tree = block[0]; |
||
| 108 | pmbaty | 17 | unsigned mvp, *lastm, rmoves[256]; |
| 18 | int temp, value; |
||
| 33 | pmbaty | 19 | #if !defined(NOEGTB) |
| 108 | pmbaty | 20 | int tb_value; |
| 33 | pmbaty | 21 | #endif |
| 22 | |||
| 23 | /* |
||
| 24 | ************************************************************ |
||
| 25 | * * |
||
| 26 | * If the position at the root is a draw, based on EGTB * |
||
| 27 | * results, we are going to behave differently. We will * |
||
| 28 | * extract the root moves that are draws, and toss the * |
||
| 29 | * losers out. Then, we will do a normal search on the * |
||
| 30 | * moves that draw to try and chose the drawing move that * |
||
| 31 | * gives our opponent the best chance to make an error. * |
||
| 32 | * This search will be done sans EGTB probes since we al- * |
||
| 33 | * ready know this is a draw at the root. We simply find * |
||
| 34 | * the best move (based on search/eval) that preserves the * |
||
| 35 | * draw. * |
||
| 36 | * * |
||
| 37 | ************************************************************ |
||
| 38 | */ |
||
| 39 | #if !defined(NOEGTB) |
||
| 40 | EGTB_draw = 0; |
||
| 41 | if (EGTBlimit && TotalAllPieces <= EGTBlimit && |
||
| 42 | Castle(1, white) + Castle(1, black) == 0 && |
||
| 43 | EGTBProbe(tree, 1, wtm, &tb_value)) { |
||
| 44 | if (swindle_mode && (tb_value == DrawScore(wtm))) |
||
| 45 | if ((wtm && Material > 0) || (!wtm && Material < 0)) |
||
| 46 | EGTB_draw = 1; |
||
| 47 | } |
||
| 48 | #endif |
||
| 49 | /* |
||
| 50 | ************************************************************ |
||
| 51 | * * |
||
| 52 | * First, use GenerateMoves() to generate the set of legal * |
||
| 53 | * moves from the root position. * |
||
| 54 | * * |
||
| 55 | ************************************************************ |
||
| 56 | */ |
||
| 57 | lastm = GenerateCaptures(tree, 1, wtm, rmoves); |
||
| 58 | lastm = GenerateNoncaptures(tree, 1, wtm, lastm); |
||
| 59 | n_root_moves = lastm - rmoves; |
||
| 108 | pmbaty | 60 | for (mvp = 0; mvp < (unsigned int) n_root_moves; mvp++) // Pierre-Marie Baty -- added type cast |
| 61 | root_moves[mvp].move = rmoves[mvp]; |
||
| 33 | pmbaty | 62 | /* |
| 63 | ************************************************************ |
||
| 64 | * * |
||
| 65 | * Now make each move and use Quiesce() to analyze the * |
||
| 66 | * potential captures and return a minimax score. * |
||
| 67 | * * |
||
| 68 | * Special case: if this is an egtb draw at the root, * |
||
| 69 | * then this is where we cull the non-drawing moves by * |
||
| 70 | * doing an EGTB probe for each move. Any moves that lose * |
||
| 71 | * are left with a very bad sorting score to move them to * |
||
| 72 | * the end of the root move list. * |
||
| 73 | * * |
||
| 74 | ************************************************************ |
||
| 75 | */ |
||
| 108 | pmbaty | 76 | abort_search = 0; |
| 77 | for (mvp = 0; mvp < (unsigned int) n_root_moves; mvp++) { // Pierre-Marie Baty -- added type cast |
||
| 33 | pmbaty | 78 | value = -4000000; |
| 79 | #if defined(TRACE) |
||
| 80 | if (trace_level >= 1) { |
||
| 108 | pmbaty | 81 | tree->curmv[1] = root_moves[mvp].move; |
| 82 | Trace(tree, 1, 0, wtm, -MATE, MATE, "RootMoves()", serial, HASH, |
||
| 83 | mvp + 1); |
||
| 33 | pmbaty | 84 | } |
| 85 | #endif |
||
| 108 | pmbaty | 86 | MakeMove(tree, 1, wtm, root_moves[mvp].move); |
| 33 | pmbaty | 87 | tree->nodes_searched++; |
| 88 | if (!Check(wtm)) |
||
| 89 | do { |
||
| 108 | pmbaty | 90 | tree->curmv[1] = root_moves[mvp].move; |
| 33 | pmbaty | 91 | #if !defined(NOEGTB) |
| 92 | if (TotalAllPieces <= EGTBlimit && EGTB_draw && |
||
| 93 | Castle(1, white) + Castle(1, black) == 0) { |
||
| 108 | pmbaty | 94 | temp = EGTBProbe(tree, 2, Flip(wtm), &tb_value); |
| 95 | if (temp && tb_value != DrawScore(Flip(wtm))) |
||
| 33 | pmbaty | 96 | break; |
| 97 | } |
||
| 98 | #endif |
||
| 108 | pmbaty | 99 | value = -Quiesce(tree, 2, Flip(wtm), -MATE, MATE, 0); |
| 33 | pmbaty | 100 | /* |
| 101 | ************************************************************ |
||
| 102 | * * |
||
| 103 | * Add in a bonus if this move is part of the previous * |
||
| 104 | * principal variation. It was good in the search, we * |
||
| 105 | * should try it first now. * |
||
| 106 | * * |
||
| 107 | ************************************************************ |
||
| 108 | */ |
||
| 108 | pmbaty | 109 | if ((Piece(root_moves[mvp].move) == Piece(last_pv.path[1])) |
| 110 | && (From(root_moves[mvp].move) == From(last_pv.path[1])) |
||
| 111 | && (To(root_moves[mvp].move) == To(last_pv.path[1])) |
||
| 112 | && (Captured(root_moves[mvp].move) == Captured(last_pv.path[1])) |
||
| 113 | && (Promote(root_moves[mvp].move) == Promote(last_pv.path[1]))) |
||
| 33 | pmbaty | 114 | value += 2000000; |
| 115 | /* |
||
| 116 | ************************************************************ |
||
| 117 | * * |
||
| 118 | * Fudge the score for promotions so that promotion to a * |
||
| 119 | * queen is tried first. * |
||
| 120 | * * |
||
| 121 | ************************************************************ |
||
| 122 | */ |
||
| 108 | pmbaty | 123 | if (Promote(root_moves[mvp].move) && |
| 124 | (Promote(root_moves[mvp].move) != queen)) |
||
| 33 | pmbaty | 125 | value -= 50; |
| 126 | } while (0); |
||
| 108 | pmbaty | 127 | root_moves[mvp].path = tree->pv[1]; |
| 128 | root_moves[mvp].path.pathv = value; |
||
| 129 | root_moves[mvp].status = 0; |
||
| 130 | root_moves[mvp].bm_age = 0; |
||
| 131 | UnmakeMove(tree, 1, wtm, root_moves[mvp].move); |
||
| 33 | pmbaty | 132 | } |
| 133 | /* |
||
| 134 | ************************************************************ |
||
| 135 | * * |
||
| 136 | * Sort the moves into order based on the scores returned * |
||
| 137 | * by Quiesce() which includes evaluation + captures. * |
||
| 138 | * * |
||
| 139 | ************************************************************ |
||
| 140 | */ |
||
| 108 | pmbaty | 141 | SortRootMoves(); |
| 33 | pmbaty | 142 | /* |
| 143 | ************************************************************ |
||
| 144 | * * |
||
| 145 | * Trim the move list to eliminate those moves that hang * |
||
| 146 | * the king and are illegal. This also culls any non- * |
||
| 147 | * drawing moves when we are in the swindle-mode situation * |
||
| 148 | * and want to do a normal search but only on moves that * |
||
| 149 | * preserve the draw. * |
||
| 150 | * * |
||
| 151 | ************************************************************ |
||
| 152 | */ |
||
| 153 | for (; n_root_moves; n_root_moves--) |
||
| 108 | pmbaty | 154 | if (root_moves[n_root_moves - 1].path.pathv > -3000000) |
| 33 | pmbaty | 155 | break; |
| 108 | pmbaty | 156 | if (root_moves[0].path.pathv > 1000000) |
| 157 | root_moves[0].path.pathv -= 2000000; |
||
| 33 | pmbaty | 158 | /* |
| 159 | ************************************************************ |
||
| 160 | * * |
||
| 161 | * Debugging output to dump root move list and the stuff * |
||
| 162 | * used to sort them, for testing and debugging. * |
||
| 163 | * * |
||
| 164 | ************************************************************ |
||
| 165 | */ |
||
| 108 | pmbaty | 166 | if (display_options & 128) { |
| 167 | Print(128, "%d moves at root\n", n_root_moves); |
||
| 168 | Print(128, " score move/pv\n"); |
||
| 169 | for (mvp = 0; mvp < (unsigned int) n_root_moves; mvp++) // Pierre-Marie Baty -- added type cast |
||
| 170 | Print(128, "%10s %s\n", DisplayEvaluation(root_moves[mvp].path.pathv, |
||
| 171 | wtm), DisplayPath(tree, wtm, &root_moves[mvp].path)); |
||
| 33 | pmbaty | 172 | } |
| 173 | /* |
||
| 174 | ************************************************************ |
||
| 175 | * * |
||
| 108 | pmbaty | 176 | * Finally, before we return the list of moves, we need to * |
| 177 | * set the values to an impossible negative value so that * |
||
| 178 | * as we sort the root move list after fail highs and lows * |
||
| 179 | * the un-searched moves won't pop to the top of the list. * |
||
| 33 | pmbaty | 180 | * * |
| 181 | ************************************************************ |
||
| 182 | */ |
||
| 108 | pmbaty | 183 | for (mvp = 1; mvp < (unsigned int) n_root_moves; mvp++) // Pierre-Marie Baty -- added type cast |
| 184 | root_moves[mvp].path.pathv = -99999999; |
||
| 33 | pmbaty | 185 | return; |
| 186 | } |