@@ -114,55 +114,85 @@ int evaluateTactics(const chess::Board& board) {
114114 if (tacticsCache.find (hash) != tacticsCache.end ()) return tacticsCache[hash];
115115
116116 int score = 0 ;
117-
118- chess::Square myKing = board.kingSq (board.sideToMove ());
119- chess::Square enemyKing = board.kingSq (~board.sideToMove ());
117+ U64 myPieces = board.us (board.sideToMove ()).getBits ();
118+ U64 enemyPieces = board.them (board.sideToMove ()).getBits ();
120119
121120 // **1. Pin Check**
122- for (chess::Square pieceSq : scan_reversed (board.us (board.sideToMove ()).getBits ())) {
123- if (isPinned (const_cast <chess::Board&>(board), pieceSq)) score -= 30 ;
121+ U64 pinnedPieces = myPieces; // Cache the bitboard
122+ while (pinnedPieces) {
123+ int pieceSq = __builtin_ctzll (pinnedPieces);
124+ pinnedPieces &= pinnedPieces - 1 ;
125+ if (isPinned (const_cast <chess::Board&>(board), chess::Square (pieceSq))) {
126+ score -= 30 ;
127+ }
124128 }
125129
126- // **2. Skewer Check** (Updated)
127- for (chess::Square attackerSq : scan_reversed (board.pieces (chess::PieceType::ROOK, board.sideToMove ()).getBits () |
128- board.pieces (chess::PieceType::QUEEN, board.sideToMove ()).getBits ())) {
129- for (chess::Square targetSq : scan_reversed (board.them (board.sideToMove ()).getBits ())) {
130- for (chess::Square behindTargetSq : scan_reversed (board.them (board.sideToMove ()).getBits ())) {
131- if (isSkewer (1ULL <<attackerSq.index (), 1ULL <<targetSq.index (), 1ULL <<behindTargetSq.index ())) {
132- score += 40 ; // Skewer usually wins material
130+ // **2. Skewer Check** (Optimized)
131+ U64 skewerAttackers = board.pieces (chess::PieceType::ROOK, board.sideToMove ()).getBits () |
132+ board.pieces (chess::PieceType::QUEEN, board.sideToMove ()).getBits ();
133+ while (skewerAttackers) {
134+ int attackerSq = __builtin_ctzll (skewerAttackers);
135+ skewerAttackers &= skewerAttackers - 1 ;
136+
137+ U64 targetPieces = enemyPieces; // Cache enemy bitboard
138+ while (targetPieces) {
139+ int targetSq = __builtin_ctzll (targetPieces);
140+ targetPieces &= targetPieces - 1 ;
141+
142+ U64 behindTarget = enemyPieces;
143+ while (behindTarget) {
144+ int behindTargetSq = __builtin_ctzll (behindTarget);
145+ behindTarget &= behindTarget - 1 ;
146+
147+ if (isSkewer (1ULL << attackerSq, 1ULL << targetSq, 1ULL << behindTargetSq)) {
148+ score += 40 ;
133149 }
134150 }
135151 }
136152 }
137153
138- // **3. Discovered Attack Check** (Updated)
139- for (chess::Square movingSq : scan_reversed (board.us (board.sideToMove ()).getBits ())) {
140- for (chess::Square attackerSq : scan_reversed (board.pieces (chess::PieceType::underlying::ROOK, board.sideToMove ()).getBits () |
141- board.pieces (chess::PieceType::underlying::BISHOP, board.sideToMove ()).getBits () |
142- board.pieces (chess::PieceType::underlying::QUEEN, board.sideToMove ()).getBits ())) {
143- for (chess::Square targetSq : scan_reversed (board.them (board.sideToMove ()).getBits ())) {
144- if (isDiscoveredAttack (1ULL <<movingSq.index (), 1ULL <<attackerSq.index (), 1ULL <<targetSq.index ())) {
145- score += 30 ; // Discovered attacks are strong
146- }
154+ // **3. Discovered Attack Check (Optimized)**
155+ U64 mySlidingPieces = board.pieces (chess::PieceType::ROOK, board.sideToMove ()).getBits () |
156+ board.pieces (chess::PieceType::BISHOP, board.sideToMove ()).getBits () |
157+ board.pieces (chess::PieceType::QUEEN, board.sideToMove ()).getBits ();
158+ while (mySlidingPieces) {
159+ int attackerSq = __builtin_ctzll (mySlidingPieces);
160+ mySlidingPieces &= mySlidingPieces - 1 ;
161+
162+ U64 targets = enemyPieces;
163+ while (targets) {
164+ int targetSq = __builtin_ctzll (targets);
165+ targets &= targets - 1 ;
166+
167+ if (isDiscoveredAttack (1ULL << attackerSq, 1ULL << attackerSq, 1ULL << targetSq)) {
168+ score += 30 ;
147169 }
148170 }
149171 }
150172
151- // **4. X-Ray Attack**
152- for (chess::Square pieceSq : scan_reversed (board.pieces (chess::PieceType::underlying::ROOK, board.sideToMove ()).getBits () |
153- board.pieces (chess::PieceType::underlying::QUEEN, board.sideToMove ()).getBits ())) {
154- for (chess::Square enemyPieceSq : scan_reversed (board.them (board.sideToMove ()).getBits ())) {
155- if (isXRayAttack (board.pieces (chess::PieceType::underlying::QUEEN, board.sideToMove ()).getBits (),
156- board.pieces (chess::PieceType::underlying::ROOK, board.sideToMove ()).getBits (),
157- 1ULL <<enemyPieceSq.index ())) {
173+ // **4. X-Ray Attack Check**
174+ U64 xRayPieces = board.pieces (chess::PieceType::ROOK, board.sideToMove ()).getBits () |
175+ board.pieces (chess::PieceType::QUEEN, board.sideToMove ()).getBits ();
176+ while (xRayPieces) {
177+ int pieceSq = __builtin_ctzll (xRayPieces);
178+ xRayPieces &= xRayPieces - 1 ;
179+
180+ U64 enemyTargets = enemyPieces;
181+ while (enemyTargets) {
182+ int enemyPieceSq = __builtin_ctzll (enemyTargets);
183+ enemyTargets &= enemyTargets - 1 ;
184+
185+ if (isXRayAttack (1ULL << pieceSq, 1ULL << enemyPieceSq, 1ULL << board.kingSq (~board.sideToMove ()).index ())) {
158186 score += 10 ;
159187 }
160188 }
161189 }
190+
162191 tacticsCache[hash] = score;
163192 return score;
164193}
165194
195+
166196// **8. King Patterns (Mobility & Escape Routes)**
167197inline U64 getKingMobility (U64 king, U64 friendlyPieces) {
168198 return (king << 8 | king >> 8 | king << 1 | king >> 1 ) & ~friendlyPieces;
0 commit comments