@@ -62,7 +62,7 @@ int backward(U64 whitePawns, U64 blackPawns) {
6262inline 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)
107107inline 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}
137137inline 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) {
217217inline 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)**
224224inline 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 ;
0 commit comments