mirror of
https://github.com/sockspls/badfish
synced 2025-04-30 00:33:09 +00:00
Use std library to sort moves
Functional change due to the fact that now pick_best() is stable, but should be no change in strenght. Example code and ideas by Rein Halbersma. Signed-off-by: Marco Costalba <mcostalba@gmail.com>
This commit is contained in:
parent
0cfb30e5be
commit
fbdabe2975
5 changed files with 36 additions and 82 deletions
|
@ -245,7 +245,7 @@ inline Bitboard attack_span_mask(Color c, Square s) {
|
|||
|
||||
inline bool squares_aligned(Square s1, Square s2, Square s3) {
|
||||
return (BetweenBB[s1][s2] | BetweenBB[s1][s3] | BetweenBB[s2][s3])
|
||||
& ((1ULL << s1) | (1ULL << s2) | (1ULL << s3));
|
||||
& ( SetMaskBB[s1] | SetMaskBB[s2] | SetMaskBB[s3]);
|
||||
}
|
||||
|
||||
|
||||
|
|
57
src/move.h
57
src/move.h
|
@ -55,7 +55,7 @@ inline bool operator<(const MoveStack& f, const MoveStack& s) { return f.score <
|
|||
|
||||
// An helper insertion sort implementation, works with pointers and iterators
|
||||
template<typename T, typename K>
|
||||
inline void insertion_sort(K firstMove, K lastMove)
|
||||
inline void sort(K firstMove, K lastMove)
|
||||
{
|
||||
T value;
|
||||
K cur, p, d;
|
||||
|
@ -74,61 +74,6 @@ inline void insertion_sort(K firstMove, K lastMove)
|
|||
}
|
||||
}
|
||||
|
||||
// Our dedicated sort in range [firstMove, lastMove), first splits
|
||||
// positive scores from ramining then order seaprately the two sets.
|
||||
template<typename T>
|
||||
inline void sort_moves(T* firstMove, T* lastMove, T** lastPositive)
|
||||
{
|
||||
T tmp;
|
||||
T *p, *d;
|
||||
|
||||
d = lastMove;
|
||||
p = firstMove - 1;
|
||||
|
||||
d->score = -1; // right guard
|
||||
|
||||
// Split positives vs non-positives
|
||||
do {
|
||||
while ((++p)->score > 0) {}
|
||||
|
||||
if (p != d)
|
||||
{
|
||||
while (--d != p && d->score <= 0) {}
|
||||
|
||||
tmp = *p;
|
||||
*p = *d;
|
||||
*d = tmp;
|
||||
}
|
||||
|
||||
} while (p != d);
|
||||
|
||||
// Sort just positive scored moves, remaining only when we get there
|
||||
insertion_sort<T, T*>(firstMove, p);
|
||||
*lastPositive = p;
|
||||
}
|
||||
|
||||
// Picks up the best move in range [curMove, lastMove), one per cycle.
|
||||
// It is faster then sorting all the moves in advance when moves are few,
|
||||
// as normally are the possible captures. Note that is not a stable alghoritm.
|
||||
template<typename T>
|
||||
inline T pick_best(T* curMove, T* lastMove)
|
||||
{
|
||||
T bestMove, tmp;
|
||||
|
||||
bestMove = *curMove;
|
||||
while (++curMove != lastMove)
|
||||
{
|
||||
if (bestMove < *curMove)
|
||||
{
|
||||
tmp = *curMove;
|
||||
*curMove = bestMove;
|
||||
bestMove = tmp;
|
||||
}
|
||||
}
|
||||
return bestMove;
|
||||
}
|
||||
|
||||
|
||||
inline Square move_from(Move m) {
|
||||
return Square((m >> 6) & 0x3F);
|
||||
}
|
||||
|
|
|
@ -18,6 +18,7 @@
|
|||
along with this program. If not, see <http://www.gnu.org/licenses/>.
|
||||
*/
|
||||
|
||||
#include <algorithm>
|
||||
#include <cassert>
|
||||
|
||||
#include "movegen.h"
|
||||
|
@ -49,6 +50,19 @@ namespace {
|
|||
const uint8_t QsearchWithoutChecksTable[] = { PH_TT_MOVE, PH_QCAPTURES, PH_STOP };
|
||||
const uint8_t QsearchRecapturesTable[] = { PH_TT_MOVE, PH_QRECAPTURES, PH_STOP };
|
||||
const uint8_t ProbCutTable[] = { PH_TT_MOVE, PH_GOOD_PROBCUT, PH_STOP };
|
||||
|
||||
// Unary predicate used by std::partition to split positive scores from ramining
|
||||
// ones so to sort separately the two sets, and with the second sort delayed.
|
||||
inline bool has_positive_score(const MoveStack& move) { return move.score > 0; }
|
||||
|
||||
// Picks and pushes to the front the best move in range [firstMove, lastMove),
|
||||
// it is faster then sorting all the moves in advance when moves are few, as
|
||||
// normally are the possible captures.
|
||||
inline MoveStack* pick_best(MoveStack* firstMove, MoveStack* lastMove)
|
||||
{
|
||||
std::swap(*firstMove, *std::max_element(firstMove, lastMove));
|
||||
return firstMove;
|
||||
}
|
||||
}
|
||||
|
||||
/// Constructors for the MovePicker class. As arguments we pass information
|
||||
|
@ -164,14 +178,15 @@ void MovePicker::go_next_phase() {
|
|||
case PH_NONCAPTURES_1:
|
||||
lastNonCapture = lastMove = generate<MV_NON_CAPTURE>(pos, moves);
|
||||
score_noncaptures();
|
||||
sort_moves(moves, lastNonCapture, &lastMove);
|
||||
lastMove = std::partition(curMove, lastMove, has_positive_score);
|
||||
sort<MoveStack>(curMove, lastMove);
|
||||
return;
|
||||
|
||||
case PH_NONCAPTURES_2:
|
||||
curMove = lastMove;
|
||||
lastMove = lastNonCapture;
|
||||
if (depth >= 3 * ONE_PLY)
|
||||
insertion_sort<MoveStack>(curMove, lastMove);
|
||||
sort<MoveStack>(curMove, lastMove);
|
||||
return;
|
||||
|
||||
case PH_BAD_CAPTURES:
|
||||
|
@ -306,7 +321,7 @@ Move MovePicker::get_next_move() {
|
|||
break;
|
||||
|
||||
case PH_GOOD_CAPTURES:
|
||||
move = pick_best(curMove++, lastMove).move;
|
||||
move = pick_best(curMove++, lastMove)->move;
|
||||
if (move != ttMove)
|
||||
{
|
||||
assert(captureThreshold <= 0); // Otherwise we must use see instead of see_sign
|
||||
|
@ -324,7 +339,7 @@ Move MovePicker::get_next_move() {
|
|||
break;
|
||||
|
||||
case PH_GOOD_PROBCUT:
|
||||
move = pick_best(curMove++, lastMove).move;
|
||||
move = pick_best(curMove++, lastMove)->move;
|
||||
if ( move != ttMove
|
||||
&& pos.see(move) > captureThreshold)
|
||||
return move;
|
||||
|
@ -349,12 +364,12 @@ Move MovePicker::get_next_move() {
|
|||
break;
|
||||
|
||||
case PH_BAD_CAPTURES:
|
||||
move = pick_best(curMove++, lastMove).move;
|
||||
move = pick_best(curMove++, lastMove)->move;
|
||||
return move;
|
||||
|
||||
case PH_EVASIONS:
|
||||
case PH_QCAPTURES:
|
||||
move = pick_best(curMove++, lastMove).move;
|
||||
move = pick_best(curMove++, lastMove)->move;
|
||||
if (move != ttMove)
|
||||
return move;
|
||||
break;
|
||||
|
|
|
@ -513,14 +513,14 @@ bool Position::pl_move_is_legal(Move m, Bitboard pinned) const {
|
|||
assert(piece_color(piece_on(from)) == us);
|
||||
assert(piece_on(king_square(us)) == make_piece(us, KING));
|
||||
|
||||
// En passant captures are a tricky special case. Because they are
|
||||
// rather uncommon, we do it simply by testing whether the king is attacked
|
||||
// after the move is made
|
||||
// En passant captures are a tricky special case. Because they are rather
|
||||
// uncommon, we do it simply by testing whether the king is attacked after
|
||||
// the move is made.
|
||||
if (move_is_ep(m))
|
||||
{
|
||||
Color them = opposite_color(us);
|
||||
Square to = move_to(m);
|
||||
Square capsq = make_square(square_file(to), square_rank(from));
|
||||
Square capsq = to + Square(us == WHITE ? -8 : 8);
|
||||
Square ksq = king_square(us);
|
||||
Bitboard b = occupied_squares();
|
||||
|
||||
|
|
|
@ -79,16 +79,9 @@ namespace {
|
|||
Move pv[PLY_MAX_PLUS_2];
|
||||
};
|
||||
|
||||
// RootMoveList struct is just a vector of RootMove objects,
|
||||
// with an handful of methods above the standard ones.
|
||||
// RootMoveList struct is mainly a std::vector of RootMove objects
|
||||
struct RootMoveList : public std::vector<RootMove> {
|
||||
|
||||
typedef std::vector<RootMove> Base;
|
||||
|
||||
void init(Position& pos, Move searchMoves[]);
|
||||
void sort() { insertion_sort<RootMove, Base::iterator>(begin(), end()); }
|
||||
void sort_first(int n) { insertion_sort<RootMove, Base::iterator>(begin(), begin() + n); }
|
||||
|
||||
int bestMoveChanges;
|
||||
};
|
||||
|
||||
|
@ -1219,7 +1212,7 @@ split_point_start: // At split points actual search starts from here
|
|||
// because all the values but the first are usually set to
|
||||
// -VALUE_INFINITE and we want to keep the same order for all
|
||||
// the moves but the new PV that goes to head.
|
||||
Rml.sort_first(moveCount);
|
||||
sort<RootMove>(Rml.begin(), Rml.begin() + moveCount);
|
||||
|
||||
// Update alpha. In multi-pv we don't use aspiration window, so set
|
||||
// alpha equal to minimum score among the PV lines searched so far.
|
||||
|
@ -1555,7 +1548,7 @@ split_point_start: // At split points actual search starts from here
|
|||
bool connected_moves(const Position& pos, Move m1, Move m2) {
|
||||
|
||||
Square f1, t1, f2, t2;
|
||||
Piece p;
|
||||
Piece p1, p2;
|
||||
|
||||
assert(m1 && move_is_ok(m1));
|
||||
assert(m2 && move_is_ok(m2));
|
||||
|
@ -1573,17 +1566,18 @@ split_point_start: // At split points actual search starts from here
|
|||
return true;
|
||||
|
||||
// Case 3: Moving through the vacated square
|
||||
if ( piece_is_slider(pos.piece_on(f2))
|
||||
p2 = pos.piece_on(f2);
|
||||
if ( piece_is_slider(p2)
|
||||
&& bit_is_set(squares_between(f2, t2), f1))
|
||||
return true;
|
||||
|
||||
// Case 4: The destination square for m2 is defended by the moving piece in m1
|
||||
p = pos.piece_on(t1);
|
||||
if (bit_is_set(pos.attacks_from(p, t1), t2))
|
||||
p1 = pos.piece_on(t1);
|
||||
if (bit_is_set(pos.attacks_from(p1, t1), t2))
|
||||
return true;
|
||||
|
||||
// Case 5: Discovered check, checking piece is the piece moved in m1
|
||||
if ( piece_is_slider(p)
|
||||
if ( piece_is_slider(p1)
|
||||
&& bit_is_set(squares_between(t1, pos.king_square(pos.side_to_move())), f2)
|
||||
&& !bit_is_set(squares_between(t1, pos.king_square(pos.side_to_move())), t2))
|
||||
{
|
||||
|
@ -2093,7 +2087,7 @@ split_point_start: // At split points actual search starts from here
|
|||
break;
|
||||
}
|
||||
|
||||
Rml.sort();
|
||||
sort<RootMove>(Rml.begin(), Rml.end());
|
||||
}
|
||||
|
||||
} // namespace
|
||||
|
|
Loading…
Add table
Reference in a new issue