Skip to content

Commit d5afdb3

Browse files
authored
maybe slow, but works for first few depths
1 parent b6ae3d8 commit d5afdb3

File tree

12 files changed

+83
-78
lines changed

12 files changed

+83
-78
lines changed

chess.hpp

Lines changed: 12 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -1815,13 +1815,13 @@ class Board {
18151815
half_moves(half_moves),
18161816
captured_piece(captured_piece) {}
18171817
};
1818-
std::vector<Move> move_stack;
18191818
enum class PrivateCtor { CREATE };
18201819

18211820
// private constructor to avoid initialization
18221821
Board(PrivateCtor) {}
18231822

18241823
public:
1824+
std::vector<Move> move_stack;
18251825
explicit Board(std::string_view fen = constants::STARTPOS, bool chess960 = false) {
18261826
prev_states_.reserve(256);
18271827
chess960_ = chess960;
@@ -2138,12 +2138,18 @@ class Board {
21382138
}
21392139
Move pop() {
21402140
if (move_stack.empty()) {
2141-
return Move(); // Return an empty move instead of causing a crash
2141+
return Move(); // Return an empty move if no move to undo
2142+
}
2143+
2144+
Move move = move_stack.back();
2145+
move_stack.pop_back();
2146+
2147+
if (move.from() != chess::Square::underlying::NO_SQ && move.to() != chess::Square::underlying::NO_SQ) {
2148+
unmakeMove(move);
2149+
} else {
2150+
std::cerr << "Invalid move detected in pop()!" << std::endl;
21422151
}
2143-
2144-
Move move = move_stack.back(); // Get last move safely
2145-
move_stack.pop_back(); // Remove last move from history
2146-
unmakeMove(move); // Undo the move in board state
2152+
21472153
return move;
21482154
}
21492155

eval.cpp

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,7 +1,7 @@
11
#include "eval.h"
22

33

4-
int eval(chess::Board &board){
4+
int eval(chess::Board board){
55
//Game over
66
if (board.inCheck()&&board.isGameOver().first!=chess::GameResultReason::NONE)return MAX;
77
else if (board.isGameOver().first!=chess::GameResultReason::NONE)return 0;

eval.h

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -13,5 +13,5 @@
1313
#define Queen 900
1414
#define MATE(i) MAX-i
1515
#define MATE_DISTANCE(i) i-MAX_MATE
16-
int eval(chess::Board&);
16+
int eval(chess::Board);
1717
#endif //EVAL

patterns.cpp

Lines changed: 4 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -21,7 +21,7 @@ inline bool isDiscoveredAttack(U64 movingPiece, U64 attacker, U64 target) {
2121
inline bool isXRayAttack(U64 attacker, U64 blocker, U64 target) {
2222
return (attacker & blocker) && (attacker & target);
2323
}
24-
inline bool isTrappedPiece(const chess::Board& board, chess::Square pieceSq) {
24+
inline bool isTrappedPiece(const chess::Board board, chess::Square pieceSq) {
2525
chess::Piece piece = board.at(pieceSq);
2626
if (piece == chess::Piece::NONE) return false; // No piece → not trapped
2727

@@ -85,7 +85,7 @@ inline bool isTrappedPiece(const chess::Board& board, chess::Square pieceSq) {
8585
}
8686

8787

88-
inline bool isPinned(chess::Board& board, chess::Square pieceSq) {
88+
inline bool isPinned(chess::Board board, chess::Square pieceSq) {
8989
chess::Color side = board.at(pieceSq).color();
9090
chess::Square kingSq = board.kingSq(side);
9191

@@ -96,15 +96,15 @@ inline bool isPinned(chess::Board& board, chess::Square pieceSq) {
9696
return isPinned;
9797
}
9898

99-
int evaluateTactics(const chess::Board& board) {
99+
int evaluateTactics(const chess::Board board) {
100100
int score = 0;
101101

102102
chess::Square myKing = board.kingSq(board.sideToMove());
103103
chess::Square enemyKing = board.kingSq(~board.sideToMove());
104104

105105
// **1. Pin Check**
106106
for (chess::Square pieceSq : scan_reversed(board.us(board.sideToMove()).getBits())) {
107-
if (isPinned(const_cast<chess::Board&>(board), pieceSq)) score -= 30;
107+
if (isPinned(board, pieceSq)) score -= 30;
108108
}
109109

110110
// **2. Skewer Check** (Updated)

patterns.h

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -4,4 +4,4 @@
44

55
bool isLosingQueenPromotion(int, U64, U64, U64);
66
inline bool isLosingQueenPromotion(U64 $1, U64 $2, U64 $3, U64 $4){ return isLosingQueenPromotion(__builtin_ctzll($1), $2, $3, $4);}
7-
int evaluateTactics(const chess::Board& board);
7+
int evaluateTactics(const chess::Board board);

pawns.cpp

Lines changed: 21 additions & 21 deletions
Original file line numberDiff line numberDiff line change
@@ -62,7 +62,7 @@ int backward(U64 whitePawns, U64 blackPawns) {
6262
inline U64 getBlockedPawns(U64 pawns, U64 enemyPieces, bool isWhite) {
6363
return isWhite ? north(pawns) & enemyPieces : south(pawns) & enemyPieces;
6464
}
65-
int blockage(const chess::Board& board){
65+
int blockage(chess::Board board){
6666
return POPCOUNT64(getBlockedPawns(board.pieces(chess::PieceType::underlying::PAWN,board.sideToMove()).getBits(),board.them(board.sideToMove()).getBits(),(int)board.sideToMove()))*5;
6767
}
6868

@@ -73,7 +73,7 @@ inline U64 getHangingPawns(U64 pawns, U64 friendlyPieces) {
7373
return pawns & ~defended;
7474
}
7575

76-
int pawnIslands(const chess::Board& board){
76+
int pawnIslands(chess::Board board){
7777

7878
int islands = 0;
7979
U64 remaining = board.pieces(chess::PieceType::underlying::PAWN, board.sideToMove()).getBits();
@@ -97,22 +97,22 @@ inline U64 getDoublyIsolatedPawns(U64 pawns) {
9797
U64 isolated = getIsolatedPawns(pawns);
9898
return isolated & (isolated - 1); // More than one isolated pawn in a file
9999
}
100-
int isolated(const chess::Board& board){
100+
int isolated(chess::Board board){
101101
return POPCOUNT64(getIsolatedPawns(board.pieces(chess::PieceType::underlying::PAWN,board.sideToMove()).getBits()))*5;
102102
}
103-
int dblisolated(const chess::Board& board){
103+
int dblisolated(chess::Board board){
104104
return POPCOUNT64(getDoublyIsolatedPawns(board.pieces(chess::PieceType::underlying::PAWN,board.sideToMove()).getBits()))*10;
105105
}
106106
// **2. Holes** (Uncontested squares that cannot be controlled by pawns)
107107
inline U64 getHoles(U64 whitePawns, U64 blackPawns) {
108108
U64 pawnControl = north(whitePawns) | south(blackPawns);
109109
return ~pawnControl; // Holes are squares not controlled by any pawn
110110
}
111-
int holes(const chess::Board& board){
111+
int holes(chess::Board board){
112112
return POPCOUNT64(getHoles(board.pieces(chess::PieceType::underlying::PAWN,chess::Color::underlying::WHITE).getBits(),board.pieces(chess::PieceType::underlying::PAWN,chess::Color::underlying::BLACK).getBits()))*5;
113113
}
114114

115-
int pawnRace(const chess::Board &board) {
115+
int pawnRace(chess::Board board) {
116116
U64 myPawns = board.pieces(chess::PieceType::PAWN, board.sideToMove()).getBits();
117117
int minDistance = 8; // Maximum distance to promotion
118118
while (myPawns) {
@@ -131,7 +131,7 @@ inline U64 getWeakPawns(U64 pawns, U64 enemyPawns) {
131131
U64 backward = (north(pawns) & enemyPawns) | (south(pawns) & enemyPawns);
132132
return isolated | backward; // Any pawn that is weak
133133
}
134-
int weaks(const chess::Board &board){
134+
int weaks(chess::Board board){
135135
return POPCOUNT64(getWeakPawns(board.pieces(chess::PieceType::underlying::PAWN,board.sideToMove()).getBits(),board.pieces(chess::PieceType::underlying::PAWN,~board.sideToMove()).getBits()))*6;
136136
}
137137
inline U64 getKingMobility(U64 king, U64 enemyPieces) {
@@ -140,22 +140,22 @@ inline U64 getKingMobility(U64 king, U64 enemyPieces) {
140140

141141
return mobility & ~enemyPieces; // Remove squares occupied by enemy pieces
142142
}
143-
inline bool shouldUnderpromote(U64 pawn, U64 enemyKing, bool isWhite, U64 enemyPieces, U64 friendlyPieces, U64 promotionSquare, int gamePhase) {
143+
inline bool shouldUnderpromote(U64 pawn, U64 enemyKing, bool isWhite, U64 enemyPieces, U64 friendlyPieces, chess::Square promotionSquare, int gamePhase) {
144144
U64 kingZone = north(enemyKing) | south(enemyKing) | east(enemyKing) | west(enemyKing);
145145

146146
// **1. Stalemate Prevention**
147147
U64 kingMobility = getKingMobility(enemyKing, enemyPieces | friendlyPieces);
148148
if (kingMobility == 0) return true; // If enemy king has no legal moves → underpromotion is preferred
149149

150150
// **2. Tactical Fork or Mating Net Check (Knight Promotions)**
151-
if (promotionSquare) {
151+
if (chess::Square::back_rank(promotionSquare,chess::Color(isWhite))) {
152152
U64 knightAttacks = getKnightAttacks(promotionSquare);
153153
if (knightAttacks & enemyKing) return true; // If knight promotes with a check/fork, prefer underpromotion
154154
}
155155

156156
// **3. Underpromotion in the Opening (Forcing Move Continuation)**
157157
if (gamePhase == 1) { // Opening phase
158-
if (promotionSquare & enemyPieces) return true; // If underpromotion maintains initiative
158+
if (chess::Bitboard(1ULL<<promotionSquare.index()) & enemyPieces) return true; // If underpromotion maintains initiative
159159
}
160160

161161
// **4. Endgame Underpromotion to Avoid Immediate Loss**
@@ -170,7 +170,8 @@ inline bool shouldUnderpromote(U64 pawn, U64 enemyKing, bool isWhite, U64 enemyP
170170

171171
return false; // Default: Queen promotion is optimal
172172
}
173-
int underpromote(chess::Board& board) {
173+
int underpromote(chess::Board board) {
174+
if (board.move_stack.empty()) return 0; // No moves to undo → no underpromotion
174175
chess::Move move = board.pop();
175176

176177
// Ensure move is valid
@@ -194,7 +195,6 @@ int underpromote(chess::Board& board) {
194195
U64 enemyKingBB = 1ULL << board.kingSq(~board.sideToMove()).index();
195196
U64 enemyPieces = board.them(board.sideToMove()).getBits();
196197
U64 friendlyPieces = board.us(board.sideToMove()).getBits();
197-
U64 promotionSquare = 1ULL << move.to().index();
198198
bool isWhite = (board.sideToMove() == chess::Color::WHITE);
199199

200200
// Calculate game phase
@@ -203,7 +203,7 @@ int underpromote(chess::Board& board) {
203203
// Correct function call
204204
bool shouldUnderpromoteResult = shouldUnderpromote(
205205
pawnBB, enemyKingBB, isWhite, enemyPieces,
206-
friendlyPieces, promotionSquare, gamePhase
206+
friendlyPieces, move.to(), gamePhase
207207
);
208208

209209
board.makeMove(move);
@@ -217,14 +217,14 @@ int underpromote(chess::Board& board) {
217217
inline U64 getColorWeakness(U64 pawns) {
218218
return ~((pawns & DARK_SQUARES) | (pawns & LIGHT_SQUARES)); // Weak squares
219219
}
220-
int weakness(const chess::Board& board){
220+
int weakness(chess::Board board){
221221
return POPCOUNT64(getColorWeakness(board.pieces(chess::PieceType::underlying::PAWN,board.sideToMove()).getBits()))*10;
222222
}
223223
// **5. Pawn Shield (King Protection by Pawns)**
224224
inline U64 getPawnShield(U64 king, U64 pawns, bool isWhite) {
225225
return isWhite ? (north(king) & pawns) : (south(king) & pawns);
226226
}
227-
int pawnShield(const chess::Board &board){
227+
int pawnShield(chess::Board board){
228228
return POPCOUNT64(getPawnShield(1ULL<<board.kingSq(board.sideToMove()).index(),board.pieces(chess::PieceType::underlying::PAWN,board.sideToMove()).getBits(),(int)board.sideToMove()))*5;
229229
}
230230

@@ -258,37 +258,37 @@ inline U64 getOpenPawns(U64 pawns, U64 enemyPawns) {
258258
return pawns & ~(north(pawns) & enemyPawns); // No enemy directly in front
259259
}
260260

261-
int pawnStorm(const chess::Board &board) {
261+
int pawnStorm(chess::Board board) {
262262
U64 myPawns = board.pieces(chess::PieceType::PAWN, board.sideToMove()).getBits();
263263
U64 storm = board.sideToMove() ? north(myPawns) | north(north(myPawns))
264264
: south(myPawns) | south(south(myPawns));
265265
return POPCOUNT64(storm) * 5; // Bonus for aggressive pawn pushes
266266
}
267267

268-
int pawnLevers(const chess::Board &board) {
268+
int pawnLevers(chess::Board board) {
269269
U64 myPawns = board.pieces(chess::PieceType::PAWN, board.sideToMove()).getBits();
270270
U64 enemyPawns = board.pieces(chess::PieceType::PAWN, ~board.sideToMove()).getBits();
271271
return POPCOUNT64(getPawnLevers(myPawns, enemyPawns)) * 5; // Bonus for break opportunities
272272
}
273273

274-
int outpost(const chess::Board &board) {
274+
int outpost(chess::Board board) {
275275
U64 myKnights = board.pieces(chess::PieceType::KNIGHT, board.sideToMove()).getBits();
276276
U64 myPawns = board.pieces(chess::PieceType::PAWN, board.sideToMove()).getBits();
277277
return POPCOUNT64(getOutposts(myKnights, myPawns, board.sideToMove())) * 10; // Reward strong knights
278278
}
279-
int evaluatePawnRams(const chess::Board& board) {
279+
int evaluatePawnRams(chess::Board board) {
280280
return POPCOUNT64(getPawnRams(
281281
board.pieces(chess::PieceType::PAWN, board.sideToMove()).getBits(),
282282
board.pieces(chess::PieceType::PAWN, ~board.sideToMove()).getBits())) * 5;
283283
}
284284

285-
int evaluateUnfreePawns(const chess::Board& board) {
285+
int evaluateUnfreePawns(chess::Board board) {
286286
return POPCOUNT64(getUnfreePawns(
287287
board.pieces(chess::PieceType::PAWN, board.sideToMove()).getBits(),
288288
board.pieces(chess::PieceType::PAWN, ~board.sideToMove()).getBits())) * 7;
289289
}
290290

291-
int evaluateOpenPawns(const chess::Board& board) {
291+
int evaluateOpenPawns(chess::Board board) {
292292
return POPCOUNT64(getOpenPawns(
293293
board.pieces(chess::PieceType::PAWN, board.sideToMove()).getBits(),
294294
board.pieces(chess::PieceType::PAWN, ~board.sideToMove()).getBits())) * 3;

pawns.h

Lines changed: 16 additions & 16 deletions
Original file line numberDiff line numberDiff line change
@@ -4,19 +4,19 @@
44
// **Evaluation Function Declarations**
55
int doubled(U64, U64);
66
int backward(U64, U64);
7-
int weaks(const chess::Board&);
8-
int blockage(const chess::Board&);
9-
int pawnIslands(const chess::Board&);
10-
int isolated(const chess::Board&);
11-
int dblisolated(const chess::Board&);
12-
int holes(const chess::Board&);
13-
int pawnRace(const chess::Board&);
14-
int underpromote(chess::Board&);
15-
int weakness(const chess::Board&);
16-
int pawnShield(const chess::Board&);
17-
int pawnStorm(const chess::Board&);
18-
int pawnLevers(const chess::Board&);
19-
int outpost(const chess::Board&);
20-
int evaluatePawnRams(const chess::Board&);
21-
int evaluateUnfreePawns(const chess::Board&);
22-
int evaluateOpenPawns(const chess::Board&);
7+
int weaks(chess::Board);
8+
int blockage(chess::Board);
9+
int pawnIslands(chess::Board);
10+
int isolated(chess::Board);
11+
int dblisolated(chess::Board);
12+
int holes(chess::Board);
13+
int pawnRace(chess::Board);
14+
int underpromote(chess::Board);
15+
int weakness(chess::Board);
16+
int pawnShield(chess::Board);
17+
int pawnStorm(chess::Board);
18+
int pawnLevers(chess::Board);
19+
int outpost(chess::Board);
20+
int evaluatePawnRams(chess::Board);
21+
int evaluateUnfreePawns(chess::Board);
22+
int evaluateOpenPawns(chess::Board);

0 commit comments

Comments
 (0)