- Glaurung, a UCI chess playing engine.
- Copyright (C) 2004-2008 Tord Romstad
+ Stockfish, a UCI chess playing engine derived from Glaurung 2.1
+ Copyright (C) 2004-2008 Tord Romstad (Glaurung author)
+ Copyright (C) 2008 Marco Costalba
it under the terms of the GNU General Public License as published by
the Free Software Foundation, either version 3 of the License, or
(at your option) any later version.
it under the terms of the GNU General Public License as published by
the Free Software Foundation, either version 3 of the License, or
(at your option) any later version.
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
GNU General Public License for more details.
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
GNU General Public License for more details.
You should have received a copy of the GNU General Public License
along with this program. If not, see <http://www.gnu.org/licenses/>.
*/
You should have received a copy of the GNU General Public License
along with this program. If not, see <http://www.gnu.org/licenses/>.
*/
/// move ordering is at the current node.
MovePicker::MovePicker(const Position& p, bool pvnode, Move ttm, Move mk,
/// move ordering is at the current node.
MovePicker::MovePicker(const Position& p, bool pvnode, Move ttm, Move mk,
/// MovePicker::score_captures(), MovePicker::score_noncaptures(),
/// MovePicker::score_evasions() and MovePicker::score_qcaptures() assign a
/// numerical move ordering score to each move in a move list. The moves
/// with highest scores will be picked first by pick_move_from_list().
void MovePicker::score_captures() {
/// MovePicker::score_captures(), MovePicker::score_noncaptures(),
/// MovePicker::score_evasions() and MovePicker::score_qcaptures() assign a
/// numerical move ordering score to each move in a move list. The moves
/// with highest scores will be picked first by pick_move_from_list().
void MovePicker::score_captures() {
// Suprisingly, this appears to perform slightly better than SEE based
// move ordering. The reason is probably that in a position with a winning
// capture, capturing a more valuable (but sufficiently defended) piece
// Suprisingly, this appears to perform slightly better than SEE based
// move ordering. The reason is probably that in a position with a winning
// capture, capturing a more valuable (but sufficiently defended) piece
- Move m = moves[i].move;
- moves[i].score = pos.see(m);
- //if (moves[i].score >= 0)
- // moves[i].score = move_promotion(m) ? QueenValueMidgame
- // : pos.midgame_value_of_piece_on(move_to(m));
+ int seeValue = pos.see(moves[i].move);
+ if (seeValue >= 0)
+ {
+ if (move_promotion(moves[i].move))
+ moves[i].score = QueenValueMidgame;
+ else
+ moves[i].score = int(pos.midgame_value_of_piece_on(move_to(moves[i].move)))
+ -int(pos.type_of_piece_on(move_from(moves[i].move)));
+ } else
+ moves[i].score = seeValue;
- moves[i].score = H.move_ordering_score(pos.piece_on(move_from(m)), m);
-
- // Ensure moves in history are always sorted as first
- if (moves[i].score > 0)
- moves[i].score += 1000;
-
- moves[i].score += pos.mg_pst_delta(moves[i].move);
+ moves[i].score = H.move_ordering_score(pos.piece_on(move_from(m)), m);
- moves[i].score = pos.see(m);
- if (moves[i].score >= 0)
- moves[i].score += HistoryMax;
- }
- else
+ int seeScore = pos.see(m);
+ moves[i].score = (seeScore >= 0)? seeScore + HistoryMax : seeScore;
+ } else
moves[i].score = H.move_ordering_score(pos.piece_on(move_from(m)), m);
}
// FIXME try psqt also here
moves[i].score = H.move_ordering_score(pos.piece_on(move_from(m)), m);
}
// FIXME try psqt also here
- moves[i].score = move_promotion(m) ? QueenValueMidgame
- : pos.midgame_value_of_piece_on(move_to(m));
+ if (move_promotion(m))
+ moves[i].score = QueenValueMidgame;
+ else
+ moves[i].score = int(pos.midgame_value_of_piece_on(move_to(m)))
+ -int(pos.midgame_value_of_piece_on(move_to(m))) / 64;
assert(numOfBadCaptures < 63);
badCaptures[numOfBadCaptures++] = moves[i];
moves[i--] = moves[--numOfMoves];
assert(numOfBadCaptures < 63);
badCaptures[numOfBadCaptures++] = moves[i];
moves[i--] = moves[--numOfMoves];
while (movesPicked < numOfMoves)
{
// If this is a PV node or we have only picked a few moves, scan
// the entire move list for the best move. If many moves have already
// been searched and it is not a PV node, we are probably failing low
// anyway, so we just pick the first move from the list.
while (movesPicked < numOfMoves)
{
// If this is a PV node or we have only picked a few moves, scan
// the entire move list for the best move. If many moves have already
// been searched and it is not a PV node, we are probably failing low
// anyway, so we just pick the first move from the list.
- if (move != ttMove && pos.move_is_legal(move, pinned))
+ // Remember to change the line below if we decide to hash the qsearch!
+ // Maybe also postpone the legality check until after futility pruning?
+ if (/* move != ttMove && */ pos.pl_move_is_legal(move, pinned))
- move = moves[movesPicked++].move;
- if (move != ttMove && pos.move_is_legal(move, pinned))
+ move = moves[movesPicked++].move;
+ // Remember to change the line below if we decide to hash the qsearch!
+ if (/* move != ttMove && */ pos.pl_move_is_legal(move, pinned))
/// MovePicker::init_phase_table() initializes the PhaseTable[],
/// MainSearchPhaseIndex, EvasionPhaseIndex, QsearchWithChecksPhaseIndex
/// MovePicker::init_phase_table() initializes the PhaseTable[],
/// MainSearchPhaseIndex, EvasionPhaseIndex, QsearchWithChecksPhaseIndex
/// during program startup, and never again while the program is running.
void MovePicker::init_phase_table() {
/// during program startup, and never again while the program is running.
void MovePicker::init_phase_table() {