feat(official-bots): implement king-relative (HalfKP) encoding in NNUE (NCS-109) #80

Merged
Janis merged 2 commits from feat/NCS-116-perspective-flip into main 2026-06-24 19:33:14 +02:00

2 Commits

Author SHA1 Message Date
Janis Eccarius 2a3f0d6be3 feat(official-bots): perspective-independent training via board flip for Black (NCS-116)
Build & Test (NowChessSystems) TeamCity build failed
Training: for Black-to-move positions, mirror the board (ranks flipped,
colours swapped) before feature extraction so the model always sees the
position from the side-to-move's perspective.  Eval label is negated to
match.  Implemented in fen_to_features (board.mirror()) and __getitem__
(' b ' check in FEN string).

Inference (legacy evaluate()): applies the same flip for Black so the
model receives features in the format it was trained on.  The
scoreFromOutput negation converts back to White's absolute perspective.
Incremental accumulator path is unchanged — it uses the raw HalfKP
features with the existing sign-negation at output; the quality gain comes
from the richer training distribution.

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
2026-06-24 19:30:22 +02:00
Janis Eccarius 9d81198108 feat(official-bots): implement king-relative (HalfKP) encoding in NNUE (NCS-109)
Build & Test (NowChessSystems) TeamCity build finished
Replace absolute 768-feature encoding with dual-perspective king-relative
encoding (HalfKP style): each piece is encoded from both the white king's
and the black king's reference frame, yielding 98304 input features
(2 × 64 king-squares × 12 piece-types × 64 squares).

Key changes:
- NNUE.scala: featureIdxWhite/featureIdxBlack replace featureIndex;
  pushAccumulator now accepts childBoard and recomputes on king moves
  (castle or normal king move) instead of using stale incremental state;
  non-king moves update both perspectives incrementally (~4 column ops).
- EvaluationNNUE.scala: pass child.board to pushAccumulator.
- python/src/train.py: fen_to_features produces 98304-dim HalfKP vector;
  NNUE model input size updated to INPUT_SIZE (98304); DEFAULT_HIDDEN_SIZES
  reduced to [512, 256, 128] appropriate for sparse high-dim input.
- nnue_weights.nbai: replaced with placeholder 98304→16→8→1 model so
  tests compile and run; replace with a retrained model via Colab notebook.

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
2026-06-24 19:12:25 +02:00