1
0
Fork 0
mirror of https://github.com/sockspls/badfish synced 2025-07-15 21:39:14 +00:00

Try to cleanup movepick

Hopefully without regressions.

Signed-off-by: Marco Costalba <mcostalba@gmail.com>
This commit is contained in:
Marco Costalba 2008-10-25 15:57:19 +01:00
parent f8bc38a006
commit 4f14bd5032
2 changed files with 67 additions and 86 deletions

View file

@ -61,9 +61,8 @@ namespace {
/// search captures, promotions and some checks) and about how important good /// search captures, promotions and some checks) and about how important good
/// move ordering is at the current node. /// move ordering is at the current node.
MovePicker::MovePicker(Position& p, bool pvnode, Move ttm, Move mk, MovePicker::MovePicker(const Position& p, bool pvnode, Move ttm, Move mk,
Move k1, Move k2, Depth d) { Move k1, Move k2, Depth d) : pos(p) {
pos = &p;
pvNode = pvnode; pvNode = pvnode;
ttMove = ttm; ttMove = ttm;
mateKiller = (mk == ttm)? MOVE_NONE : mk; mateKiller = (mk == ttm)? MOVE_NONE : mk;
@ -112,16 +111,13 @@ Move MovePicker::get_next_move() {
// Next phase // Next phase
phaseIndex++; phaseIndex++;
switch (PhaseTable[phaseIndex]) { switch (PhaseTable[phaseIndex]) {
case PH_TT_MOVE: case PH_TT_MOVE:
if (ttMove != MOVE_NONE) if (ttMove != MOVE_NONE)
{ {
assert(move_is_ok(ttMove)); assert(move_is_ok(ttMove));
Move m = generate_move_if_legal(*pos, ttMove, pinned); if (generate_move_if_legal(pos, ttMove, pinned) != MOVE_NONE)
if (m != MOVE_NONE) return ttMove;
{
assert(m == ttMove);
return m;
}
} }
break; break;
@ -129,17 +125,13 @@ Move MovePicker::get_next_move() {
if (mateKiller != MOVE_NONE) if (mateKiller != MOVE_NONE)
{ {
assert(move_is_ok(mateKiller)); assert(move_is_ok(mateKiller));
Move m = generate_move_if_legal(*pos, mateKiller, pinned); if (generate_move_if_legal(pos, mateKiller, pinned) != MOVE_NONE)
if (m != MOVE_NONE) return mateKiller;
{
assert(m == mateKiller);
return m;
}
} }
break; break;
case PH_GOOD_CAPTURES: case PH_GOOD_CAPTURES:
numOfMoves = generate_captures(*pos, moves); numOfMoves = generate_captures(pos, moves);
score_captures(); score_captures();
movesPicked = 0; movesPicked = 0;
break; break;
@ -149,26 +141,26 @@ Move MovePicker::get_next_move() {
break; break;
case PH_NONCAPTURES: case PH_NONCAPTURES:
numOfMoves = generate_noncaptures(*pos, moves); numOfMoves = generate_noncaptures(pos, moves);
score_noncaptures(); score_noncaptures();
movesPicked = 0; movesPicked = 0;
break; break;
case PH_EVASIONS: case PH_EVASIONS:
assert(pos->is_check()); assert(pos.is_check());
numOfMoves = generate_evasions(*pos, moves); numOfMoves = generate_evasions(pos, moves);
score_evasions(); score_evasions();
movesPicked = 0; movesPicked = 0;
break; break;
case PH_QCAPTURES: case PH_QCAPTURES:
numOfMoves = generate_captures(*pos, moves); numOfMoves = generate_captures(pos, moves);
score_qcaptures(); score_qcaptures();
movesPicked = 0; movesPicked = 0;
break; break;
case PH_QCHECKS: case PH_QCHECKS:
numOfMoves = generate_checks(*pos, moves, dc); numOfMoves = generate_checks(pos, moves, dc);
movesPicked = 0; movesPicked = 0;
break; break;
@ -190,15 +182,13 @@ Move MovePicker::get_next_move() {
Move MovePicker::get_next_move(Lock &lock) { Move MovePicker::get_next_move(Lock &lock) {
Move m;
lock_grab(&lock); lock_grab(&lock);
if (finished) if (finished)
{ {
lock_release(&lock); lock_release(&lock);
return MOVE_NONE; return MOVE_NONE;
} }
m = get_next_move(); Move m = get_next_move();
if (m == MOVE_NONE) if (m == MOVE_NONE)
finished = true; finished = true;
@ -224,14 +214,14 @@ void MovePicker::score_captures() {
// the subtree size. // the subtree size.
for (int i = 0; i < numOfMoves; i++) for (int i = 0; i < numOfMoves; i++)
{ {
int seeValue = pos->see(moves[i].move); int seeValue = pos.see(moves[i].move);
if (seeValue >= 0) if (seeValue >= 0)
{ {
if (move_promotion(moves[i].move)) if (move_promotion(moves[i].move))
moves[i].score = QueenValueMidgame; moves[i].score = QueenValueMidgame;
else else
moves[i].score = int(pos->midgame_value_of_piece_on(move_to(moves[i].move))) 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))); -int(pos.type_of_piece_on(move_from(moves[i].move)));
} else } else
moves[i].score = seeValue; moves[i].score = seeValue;
} }
@ -247,7 +237,7 @@ void MovePicker::score_noncaptures() {
else if (m == killer2) else if (m == killer2)
moves[i].score = HistoryMax + 1; moves[i].score = HistoryMax + 1;
else else
moves[i].score = H.move_ordering_score(pos->piece_on(move_from(m)), m); moves[i].score = H.move_ordering_score(pos.piece_on(move_from(m)), m);
} }
} }
@ -258,12 +248,12 @@ void MovePicker::score_evasions() {
Move m = moves[i].move; Move m = moves[i].move;
if (m == ttMove) if (m == ttMove)
moves[i].score = 2*HistoryMax; moves[i].score = 2*HistoryMax;
else if(!pos->square_is_empty(move_to(m))) else if (!pos.square_is_empty(move_to(m)))
{ {
int seeScore = pos->see(m); int seeScore = pos.see(m);
moves[i].score = (seeScore >= 0)? seeScore + HistoryMax : seeScore; moves[i].score = (seeScore >= 0)? seeScore + HistoryMax : seeScore;
} else } else
moves[i].score = H.move_ordering_score(pos->piece_on(move_from(m)), m); moves[i].score = H.move_ordering_score(pos.piece_on(move_from(m)), m);
} }
// FIXME try psqt also here // FIXME try psqt also here
} }
@ -277,12 +267,29 @@ void MovePicker::score_qcaptures() {
if (move_promotion(m)) if (move_promotion(m))
moves[i].score = QueenValueMidgame; moves[i].score = QueenValueMidgame;
else else
moves[i].score = int(pos->midgame_value_of_piece_on(move_to(m))) moves[i].score = int(pos.midgame_value_of_piece_on(move_to(m)))
-int(pos->midgame_value_of_piece_on(move_to(m))) / 64; -int(pos.midgame_value_of_piece_on(move_to(m))) / 64;
} }
} }
/// find_best_index() loops across the moves and returns index of
/// the highest scored one.
int MovePicker::find_best_index() {
int bestScore = -10000000, bestIndex = -1;
for (int i = movesPicked; i < numOfMoves; i++)
if (moves[i].score > bestScore)
{
bestIndex = i;
bestScore = moves[i].score;
}
return bestIndex;
}
/// MovePicker::pick_move_from_list() picks the move with the biggest score /// MovePicker::pick_move_from_list() picks the move with the biggest score
/// from a list of generated moves (moves[] or badCaptures[], depending on /// from a list of generated moves (moves[] or badCaptures[], depending on
/// the current move generation phase). It takes care not to return the /// the current move generation phase). It takes care not to return the
@ -293,18 +300,17 @@ void MovePicker::score_qcaptures() {
Move MovePicker::pick_move_from_list() { Move MovePicker::pick_move_from_list() {
int bestScore = -10000000;
int bestIndex; int bestIndex;
Move move; Move move;
switch (PhaseTable[phaseIndex]) { switch (PhaseTable[phaseIndex]) {
case PH_GOOD_CAPTURES: case PH_GOOD_CAPTURES:
assert(!pos->is_check()); assert(!pos.is_check());
assert(movesPicked >= 0); assert(movesPicked >= 0);
while (movesPicked < numOfMoves) while (movesPicked < numOfMoves)
{ {
bestScore = -10000000; int bestScore = -10000000;
bestIndex = -1; bestIndex = -1;
for (int i = movesPicked; i < numOfMoves; i++) for (int i = movesPicked; i < numOfMoves; i++)
{ {
@ -327,35 +333,23 @@ Move MovePicker::pick_move_from_list() {
moves[bestIndex] = moves[movesPicked++]; moves[bestIndex] = moves[movesPicked++];
if ( move != ttMove if ( move != ttMove
&& move != mateKiller && move != mateKiller
&& pos->move_is_legal(move, pinned)) && pos.move_is_legal(move, pinned))
return move; return move;
} }
} }
break; break;
case PH_NONCAPTURES: case PH_NONCAPTURES:
assert(!pos->is_check()); assert(!pos.is_check());
assert(movesPicked >= 0); assert(movesPicked >= 0);
while (movesPicked < numOfMoves) while (movesPicked < numOfMoves)
{ {
bestScore = -10000000;
// If this is a PV node or we have only picked a few moves, scan // 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 // 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 // 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. // anyway, so we just pick the first move from the list.
if (pvNode || movesPicked < 12) bestIndex = (pvNode || movesPicked < 12) ? find_best_index() : movesPicked;
{
bestIndex = -1;
for (int i = movesPicked; i < numOfMoves; i++)
if (moves[i].score > bestScore)
{
bestIndex = i;
bestScore = moves[i].score;
}
} else
bestIndex = movesPicked;
if (bestIndex != -1) if (bestIndex != -1)
{ {
@ -363,26 +357,19 @@ Move MovePicker::pick_move_from_list() {
moves[bestIndex] = moves[movesPicked++]; moves[bestIndex] = moves[movesPicked++];
if ( move != ttMove if ( move != ttMove
&& move != mateKiller && move != mateKiller
&& pos->move_is_legal(move, pinned)) && pos.move_is_legal(move, pinned))
return move; return move;
} }
} }
break; break;
case PH_EVASIONS: case PH_EVASIONS:
assert(pos->is_check()); assert(pos.is_check());
assert(movesPicked >= 0); assert(movesPicked >= 0);
while (movesPicked < numOfMoves) while (movesPicked < numOfMoves)
{ {
bestScore = -10000000; bestIndex = find_best_index();
bestIndex = -1;
for (int i = movesPicked; i < numOfMoves; i++)
if(moves[i].score > bestScore)
{
bestIndex = i;
bestScore = moves[i].score;
}
if (bestIndex != -1) if (bestIndex != -1)
{ {
@ -394,7 +381,7 @@ Move MovePicker::pick_move_from_list() {
break; break;
case PH_BAD_CAPTURES: case PH_BAD_CAPTURES:
assert(!pos->is_check()); assert(!pos.is_check());
assert(badCapturesPicked >= 0); assert(badCapturesPicked >= 0);
// It's probably a good idea to use SEE move ordering here, instead // It's probably a good idea to use SEE move ordering here, instead
// of just picking the first move. FIXME // of just picking the first move. FIXME
@ -403,28 +390,17 @@ Move MovePicker::pick_move_from_list() {
move = badCaptures[badCapturesPicked++].move; move = badCaptures[badCapturesPicked++].move;
if ( move != ttMove if ( move != ttMove
&& move != mateKiller && move != mateKiller
&& pos->move_is_legal(move, pinned)) && pos.move_is_legal(move, pinned))
return move; return move;
} }
break; break;
case PH_QCAPTURES: case PH_QCAPTURES:
assert(!pos->is_check()); assert(!pos.is_check());
assert(movesPicked >= 0); assert(movesPicked >= 0);
while (movesPicked < numOfMoves) while (movesPicked < numOfMoves)
{ {
bestScore = -10000000; bestIndex = (movesPicked < 4 ? find_best_index() : movesPicked);
if (movesPicked < 4)
{
bestIndex = -1;
for (int i = movesPicked; i < numOfMoves; i++)
if(moves[i].score > bestScore)
{
bestIndex = i;
bestScore = moves[i].score;
}
} else
bestIndex = movesPicked;
if (bestIndex != -1) if (bestIndex != -1)
{ {
@ -432,14 +408,14 @@ Move MovePicker::pick_move_from_list() {
moves[bestIndex] = moves[movesPicked++]; moves[bestIndex] = moves[movesPicked++];
// Remember to change the line below if we decide to hash the qsearch! // Remember to change the line below if we decide to hash the qsearch!
// Maybe also postpone the legality check until after futility pruning? // Maybe also postpone the legality check until after futility pruning?
if (/* move != ttMove && */ pos->move_is_legal(move, pinned)) if (/* move != ttMove && */ pos.move_is_legal(move, pinned))
return move; return move;
} }
} }
break; break;
case PH_QCHECKS: case PH_QCHECKS:
assert(!pos->is_check()); assert(!pos.is_check());
assert(movesPicked >= 0); assert(movesPicked >= 0);
// Perhaps we should do something better than just picking the first // Perhaps we should do something better than just picking the first
// move here? FIXME // move here? FIXME
@ -447,7 +423,7 @@ Move MovePicker::pick_move_from_list() {
{ {
move = moves[movesPicked++].move; move = moves[movesPicked++].move;
// Remember to change the line below if we decide to hash the qsearch! // Remember to change the line below if we decide to hash the qsearch!
if (/* move != ttMove && */ pos->move_is_legal(move, pinned)) if (/* move != ttMove && */ pos.move_is_legal(move, pinned))
return move; return move;
} }
break; break;
@ -458,11 +434,16 @@ Move MovePicker::pick_move_from_list() {
return MOVE_NONE; return MOVE_NONE;
} }
/// MovePicker::current_move_type() returns the type of the just
/// picked next move. It can be used in search to further differentiate
/// according to the current move type: capture, non capture, escape, etc.
MovePicker::MovegenPhase MovePicker::current_move_type() const { MovePicker::MovegenPhase MovePicker::current_move_type() const {
return PhaseTable[phaseIndex]; return PhaseTable[phaseIndex];
} }
/// MovePicker::init_phase_table() initializes the PhaseTable[], /// MovePicker::init_phase_table() initializes the PhaseTable[],
/// MainSearchPhaseIndex, EvasionPhaseIndex, QsearchWithChecksPhaseIndex /// MainSearchPhaseIndex, EvasionPhaseIndex, QsearchWithChecksPhaseIndex
/// and QsearchWithoutChecksPhaseIndex variables. It is only called once /// and QsearchWithoutChecksPhaseIndex variables. It is only called once

View file

@ -2,17 +2,17 @@
Stockfish, a UCI chess playing engine derived from Glaurung 2.1 Stockfish, a UCI chess playing engine derived from Glaurung 2.1
Copyright (C) 2004-2008 Tord Romstad (Glaurung author) Copyright (C) 2004-2008 Tord Romstad (Glaurung author)
Copyright (C) 2008 Marco Costalba Copyright (C) 2008 Marco Costalba
Stockfish is free software: you can redistribute it and/or modify Stockfish is free software: you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by it under the terms of the GNU General Public License as published by
the Free Software Foundation, either version 3 of the License, or the Free Software Foundation, either version 3 of the License, or
(at your option) any later version. (at your option) any later version.
Stockfish is distributed in the hope that it will be useful, Stockfish is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
GNU General Public License for more details. GNU General Public License for more details.
You should have received a copy of the GNU General Public License You should have received a copy of the GNU General Public License
along with this program. If not, see <http://www.gnu.org/licenses/>. along with this program. If not, see <http://www.gnu.org/licenses/>.
*/ */
@ -60,8 +60,7 @@ public:
PH_STOP PH_STOP
}; };
MovePicker(Position &p, bool pvnode, Move ttm, Move mk, Move k1, Move k2, MovePicker(const Position& p, bool pvnode, Move ttm, Move mk, Move k1, Move k2, Depth d);
Depth dpth);
Move get_next_move(); Move get_next_move();
Move get_next_move(Lock &lock); Move get_next_move(Lock &lock);
int number_of_moves() const; int number_of_moves() const;
@ -77,8 +76,9 @@ private:
void score_evasions(); void score_evasions();
void score_qcaptures(); void score_qcaptures();
Move pick_move_from_list(); Move pick_move_from_list();
int find_best_index();
Position *pos;
const Position& pos;
Move ttMove, mateKiller, killer1, killer2; Move ttMove, mateKiller, killer1, killer2;
Bitboard pinned, dc; Bitboard pinned, dc;
MoveStack moves[256], badCaptures[64]; MoveStack moves[256], badCaptures[64];