Skip to content

Commit 598da59

Browse files
committed
fix bug and improvements
1 parent d4336c8 commit 598da59

8 files changed

Lines changed: 348 additions & 91 deletions

File tree

eval.cpp

Lines changed: 199 additions & 30 deletions
Original file line numberDiff line numberDiff line change
@@ -1,11 +1,13 @@
11
#include "eval.h"
22
#include "tune.h"
33
#include <position.h>
4+
#include <iostream>
45
using namespace chess;
56
using namespace engine::eval;
7+
68
namespace engine::eval {
79
Value PawnValue = 100, KnightValue = 325, BishopValue = 350, RookValue = 500,
8-
QueenValue = 900;
10+
QueenValue = 900, KingValue = 0;
911
Value mg_pawn_table[64] = {
1012
0, 0, 0, 0, 0, 0, 0, 0, 98, 134, 61, 95, 68, 126, 34, -11,
1113
-6, 7, 26, 31, 65, 56, 25, -20, -14, 13, 6, 21, 23, 12, 17, -23,
@@ -101,56 +103,223 @@ Value *mg_pesto_table[] = {nullptr, mg_pawn_table, mg_knight_table,
101103
Value *eg_pesto_table[] = {nullptr, eg_pawn_table, eg_knight_table,
102104
eg_bishop_table, eg_rook_table, eg_queen_table,
103105
eg_king_table};
106+
Value mgMobility[] = {
107+
0, // none
108+
0, // pawn
109+
3, // knight
110+
5, // bishop
111+
2, // rook
112+
1, // queen
113+
0 // king
114+
};
115+
116+
Value egMobility[] = {0, 0, 2, 5, 3, 2, 0};
117+
Value spaceWeight=28;
104118
// tuning slop here
105119
Value eval(const chess::Board &board) {
106-
int pieceCount[10] = {
107-
board.count<PAWN, WHITE>(), board.count<KNIGHT, WHITE>(),
108-
board.count<BISHOP, WHITE>(), board.count<ROOK, WHITE>(),
109-
board.count<QUEEN, WHITE>(), board.count<PAWN, BLACK>(),
110-
board.count<KNIGHT, BLACK>(), board.count<BISHOP, BLACK>(),
111-
board.count<ROOK, BLACK>(), board.count<QUEEN, BLACK>(),
112-
};
113-
Value material = (pieceCount[0] * PawnValue + pieceCount[1] * KnightValue +
114-
pieceCount[2] * BishopValue + pieceCount[3] * RookValue +
115-
pieceCount[4] * QueenValue) -
116-
(pieceCount[5] * PawnValue + pieceCount[6] * KnightValue +
117-
pieceCount[7] * BishopValue + pieceCount[8] * RookValue +
118-
pieceCount[9] * QueenValue);
119120
constexpr int KnightPhase = 1;
120121
constexpr int BishopPhase = 1;
121122
constexpr int RookPhase = 2;
122123
constexpr int QueenPhase = 4;
123124
constexpr int TotalPhase =
124125
KnightPhase * 4 + BishopPhase * 4 + RookPhase * 4 + QueenPhase * 2;
125-
int phase = (pieceCount[1] + pieceCount[6]) * KnightPhase +
126-
(pieceCount[2] + pieceCount[7]) * BishopPhase +
127-
(pieceCount[3] + pieceCount[8]) * RookPhase +
128-
(pieceCount[4] + pieceCount[9]) * QueenPhase;
129-
phase = (phase * 256 + TotalPhase / 2) / TotalPhase;
130126
const int sign = board.sideToMove() == chess::Color::WHITE ? 1 : -1;
131-
int mgScore = material;
132-
int egScore = material;
127+
int mgScore = 0;
128+
int egScore = 0;
129+
int phase = 0;
133130
{
134-
Bitboard occ = board.occ();
131+
mgScore=egScore=board.sideToMove() == WHITE?spaceWeight:0;
132+
Bitboard occ = board.occ(), occ2=occ;
135133
while (occ) {
136-
Square i = (Square)pop_lsb(occ);
137-
auto p = board.at(i);
134+
Square sq = (Square)pop_lsb(occ),_sq=sq;
135+
auto p = board.at(sq);
138136
int _sign = 1;
139137
if (color_of(p) == BLACK) {
140138
_sign = -1;
141-
i = square_mirror(i);
139+
_sq = square_mirror(sq);
140+
}
141+
auto pt = piece_of(p);
142+
if (pt == NO_PIECE_TYPE)
143+
continue;
144+
mgScore += _sign * mg_pesto_table[pt][_sq];
145+
egScore += _sign * eg_pesto_table[pt][_sq];
146+
mgScore += _sign * piece_value(pt);
147+
egScore += _sign * piece_value(pt);
148+
switch (pt) {
149+
case KNIGHT:
150+
phase += KnightPhase;
151+
break;
152+
case BISHOP:
153+
phase += BishopPhase;
154+
break;
155+
case ROOK:
156+
phase += RookPhase;
157+
break;
158+
case QUEEN:
159+
phase += QueenPhase;
160+
break;
161+
case PAWN:
162+
break;
163+
case KING:
164+
break;
165+
default:
166+
break;
167+
}
168+
Bitboard attacks = 0;
169+
170+
switch (pt) {
171+
case KNIGHT:
172+
attacks = chess::attacks::knight(sq);
173+
break;
174+
175+
case BISHOP:
176+
attacks = chess::attacks::bishop(sq, occ2);
177+
break;
178+
179+
case ROOK:
180+
attacks = chess::attacks::rook(sq, occ2);
181+
break;
182+
183+
case QUEEN:
184+
attacks = chess::attacks::queen(sq, occ2);
185+
break;
186+
187+
default:
188+
break;
189+
}
190+
attacks &= ~board.us(color_of(p));
191+
int mobility = popcount(attacks);
192+
mgScore += _sign * mobility * mgMobility[pt];
193+
egScore += _sign * mobility * egMobility[pt];
194+
}
195+
}
196+
// Bishop pair bonus
197+
for (Color c : {WHITE, BLACK}) {
198+
if (board.count(BISHOP, c) >= 2) {
199+
int s = (c == WHITE) ? 1 : -1;
200+
mgScore += s * 30;
201+
egScore += s * 10;
202+
}
203+
}
204+
205+
// Rook on open/semi-open file
206+
for (Color c : {WHITE, BLACK}) {
207+
int s = (c == WHITE) ? 1 : -1;
208+
Bitboard rooks = board.pieces(ROOK, c);
209+
while (rooks) {
210+
Square sq = Square(pop_lsb(rooks));
211+
File f = file_of(sq);
212+
Bitboard fileMask = attacks::MASK_FILE[f];
213+
bool hasOwnPawn = (board.pieces(PAWN, c) & fileMask) != 0;
214+
bool hasEnemyPawn = (board.pieces(PAWN, ~c) & fileMask) != 0;
215+
if (!hasOwnPawn && !hasEnemyPawn) {
216+
mgScore += s * 25;
217+
egScore += s * 10;
218+
} else if (!hasOwnPawn) {
219+
mgScore += s * 15;
220+
egScore += s * 5;
221+
}
222+
}
223+
}
224+
225+
// Doubled pawn penalty
226+
for (Color c : {WHITE, BLACK}) {
227+
int s = (c == WHITE) ? 1 : -1;
228+
for (int f = 0; f < 8; f++) {
229+
int cnt = popcount(board.pieces(PAWN, c) & attacks::MASK_FILE[f]);
230+
if (cnt >= 2) {
231+
mgScore += s * -(cnt - 1) * 15;
232+
egScore += s * -(cnt - 1) * 20;
233+
}
234+
}
235+
}
236+
237+
// Isolated pawn penalty
238+
for (Color c : {WHITE, BLACK}) {
239+
int s = (c == WHITE) ? 1 : -1;
240+
Bitboard pawns = board.pieces(PAWN, c);
241+
while (pawns) {
242+
Square sq = Square(pop_lsb(pawns));
243+
File f = file_of(sq);
244+
bool isolated = true;
245+
if (f > FILE_A && (board.pieces(PAWN, c) & attacks::MASK_FILE[f - 1]))
246+
isolated = false;
247+
if (f < FILE_H && (board.pieces(PAWN, c) & attacks::MASK_FILE[f + 1]))
248+
isolated = false;
249+
if (isolated) {
250+
mgScore += s * -20;
251+
egScore += s * -15;
252+
}
253+
}
254+
}
255+
256+
// Passed pawn bonus
257+
for (Color c : {WHITE, BLACK}) {
258+
int s = (c == WHITE) ? 1 : -1;
259+
Bitboard pawns = board.pieces(PAWN, c);
260+
Bitboard enemyPawns = board.pieces(PAWN, ~c);
261+
while (pawns) {
262+
Square sq = Square(pop_lsb(pawns));
263+
Rank relRank = relative_rank(c, sq);
264+
if (relRank < RANK_2)
265+
continue;
266+
File f = file_of(sq);
267+
Bitboard passedMask = 0;
268+
int startF = std::max(0, (int)f - 1);
269+
int endF = std::min(7, (int)f + 1);
270+
for (int adjF = startF; adjF <= endF; adjF++) {
271+
if (c == WHITE) {
272+
for (int r = rank_of(sq) + 1; r <= 7; r++)
273+
passedMask |= attacks::MASK_FILE[adjF] & attacks::MASK_RANK[r];
274+
} else {
275+
for (int r = rank_of(sq) - 1; r >= 0; r--)
276+
passedMask |= attacks::MASK_FILE[adjF] & attacks::MASK_RANK[r];
277+
}
278+
}
279+
if ((passedMask & enemyPawns) == 0) {
280+
static const Value passedBonus[] = {0, 0, 10, 20, 40, 80, 160, 200};
281+
Value bonus = passedBonus[relRank];
282+
mgScore += s * bonus;
283+
egScore += s * bonus;
142284
}
143-
mgScore += _sign * mg_pesto_table[piece_of(p)][i];
144-
egScore += _sign * eg_pesto_table[piece_of(p)][i];
145285
}
146286
}
287+
288+
// King safety: pawn shelter
289+
for (Color c : {WHITE, BLACK}) {
290+
int s = (c == WHITE) ? 1 : -1;
291+
Square kingSq = board.kingSq(c);
292+
File kf = file_of(kingSq);
293+
Bitboard pawns = board.pieces(PAWN, c);
294+
int shelter = 0;
295+
int startF = std::max(0, (int)kf - 1);
296+
int endF = std::min(7, (int)kf + 1);
297+
for (int adjF = startF; adjF <= endF; adjF++) {
298+
if (c == WHITE) {
299+
for (int r = rank_of(kingSq) + 1; r <= std::min(7, rank_of(kingSq) + 3); r++) {
300+
if (pawns & (Bitboard(1) << make_sq((File)adjF, (Rank)r)))
301+
shelter += 10 - (r - rank_of(kingSq) - 1) * 3;
302+
}
303+
} else {
304+
for (int r = rank_of(kingSq) - 1; r >= std::max(0, rank_of(kingSq) - 3); r--) {
305+
if (pawns & (Bitboard(1) << make_sq((File)adjF, (Rank)r)))
306+
shelter += 10 - (rank_of(kingSq) - r - 1) * 3;
307+
}
308+
}
309+
}
310+
mgScore += s * shelter;
311+
egScore += s * shelter / 2;
312+
}
313+
314+
phase = (phase * 256 + TotalPhase / 2) / TotalPhase;
147315
Value finalScore =
148-
((mgScore * phase) + (egScore * (256 - phase))) / 256 * sign;
316+
(((mgScore * phase) + (egScore * (256 - phase))) * sign) / 256;
149317
return finalScore;
150318
}
151319
Value piece_value(PieceType pt) {
152-
Value pieces[] = {0, PawnValue, KnightValue,
153-
BishopValue, RookValue, QueenValue};
320+
Value pieces[] = {0, PawnValue, KnightValue,
321+
BishopValue, RookValue, QueenValue,
322+
KingValue};
154323
return pieces[pt];
155324
}
156325
} // namespace engine::eval

main.cpp

Lines changed: 7 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -4,12 +4,18 @@
44
#include "ucioption.h"
55
#include <iostream>
66
using namespace engine;
7+
#define STR_HELPER(x) #x
8+
#define STR(x) STR_HELPER(x)
9+
710
int main() {
811
std::cout << std::unitbuf;
912
std::cout << "cppchess_engine version " << BUILD_VERSION << '\n';
1013
options.add("Move Overhead", Option(10, 0, 1000));
1114
options.add("Hash", Option(16, 1, 1 << 25,
12-
[](const Option &o) { return std::nullopt; }));
15+
[](const Option &o) {
16+
search::tt.resize(int(o));
17+
return std::nullopt;
18+
}));
1319

1420
options.add("Clear Hash", Option(+[](const Option &) {
1521
search::tt.clear();

movepick.cpp

Lines changed: 6 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -1,14 +1,13 @@
11
#include "movepick.h"
22
#include "eval.h"
3+
#include "search.h"
34
#include <algorithm>
4-
#include <position.h>
55
using namespace chess;
66
using engine::eval::piece_value;
77
namespace engine::movepick {
8-
Value historyHeuristic[SQUARE_NB][SQUARE_NB]{};
9-
Move killerMoves[256][2];
8+
109
void orderMoves(chess::Board &board, chess::Movelist &moves, chess::Move ttMove,
11-
int ply) {
10+
int ply, const engine::search::Session& session) {
1211
std::vector<std::pair<chess::Move, Value>> scoredMoves;
1312
scoredMoves.reserve(moves.size());
1413

@@ -23,12 +22,12 @@ void orderMoves(chess::Board &board, chess::Movelist &moves, chess::Move ttMove,
2322
: piece_value(PAWN)) *
2423
10 -
2524
piece_value(board.at<PieceType>(move.from()));
26-
else if (move == killerMoves[ply][0])
25+
else if (move == session.killerMoves[ply][0])
2726
score = 8500;
28-
else if (move == killerMoves[ply][1])
27+
else if (move == session.killerMoves[ply][1])
2928
score = 8000;
3029
else
31-
score = historyHeuristic[move.from()][move.to()];
30+
score = session.historyHeuristic[move.from()][move.to()];
3231

3332
scoredMoves.emplace_back(move, score);
3433
}

movepick.h

Lines changed: 4 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -1,7 +1,8 @@
11
#pragma once
22
#include <fwd_decl.h>
3+
namespace engine::search{
4+
struct Session;
5+
} // namespace engine::search
36
namespace engine::movepick {
4-
void orderMoves(chess::Board &, chess::Movelist &, chess::Move, int);
5-
extern int historyHeuristic[64][64];
6-
extern chess::Move killerMoves[256][2];
7+
void orderMoves(chess::Board &, chess::Movelist &, chess::Move, int, const engine::search::Session&);
78
} // namespace engine::movepick

0 commit comments

Comments
 (0)