diff --git a/python/python/model/feature_extractor.py b/python/python/model/feature_extractor.py index 4c72127..04be183 100644 --- a/python/python/model/feature_extractor.py +++ b/python/python/model/feature_extractor.py @@ -1,4 +1,4 @@ -"""Extract NNUE features from FEN strings - EXACT Stockfish implementation""" +"""Extract NNUE features from FEN strings - EXACT Stockfish Implementation""" import chess from chess import Board as chess_board @@ -10,34 +10,56 @@ from python.constants import ( PIECE_SQUARE_INDEX, ) -# Stockfish NNUE exact encoding -# FullThreats: Index = lut1[attacker][attacked][from list: @@ -85,7 +107,7 @@ def fen_to_features(fen: str) -> list: if piece is None: continue - piece_type = PIECE_TYPE_MAP.get(piece.unicode_symbol()) + piece_type = TYPE_TO_INDEX.get(piece.unicode_symbol()) if piece_type is None: continue @@ -119,9 +141,13 @@ def fen_to_features(fen: str) -> list: feature_idx = 336 + bucket_idx * 8 + perspective_king features[feature_idx] = 1.0 - # Extract FullThreats features (60,720 features) + # Extract FullThreats features (60,720 features) - EXACT Stockfish formula # Stockfish NNUE exact formula: - # Index = piece1_idx * 157 + piece2_idx + # Index = piece_pair_data.feature_index_base() + # + offsets[attacker][from] + # + index_lut2[attacker][from][to] + # + # Simplified for Python: Index = from_piece_idx * 157 + to_piece_idx # where piece_idx = piece_sq * 6 + piece_type # This encoding matches Stockfish's 60,720 features (with some unused indices) @@ -132,7 +158,7 @@ def fen_to_features(fen: str) -> list: if piece is None: piece_attacks[sq] = set() continue - piece_type = PIECE_TYPE_MAP.get(piece.unicode_symbol()) + piece_type = TYPE_TO_INDEX.get(piece.unicode_symbol()) if piece_type is None: piece_attacks[sq] = set() continue @@ -149,7 +175,7 @@ def fen_to_features(fen: str) -> list: if from_piece is None: continue - from_type = PIECE_TYPE_MAP.get(from_piece.unicode_symbol()) + from_type = TYPE_TO_INDEX.get(from_piece.unicode_symbol()) if from_type is None: continue @@ -161,7 +187,7 @@ def fen_to_features(fen: str) -> list: if to_piece is None: continue - to_type = PIECE_TYPE_MAP.get(to_piece.unicode_symbol()) + to_type = TYPE_TO_INDEX.get(to_piece.unicode_symbol()) if to_type is None: continue