Skip to content

[3/6] Add MVV-LVA capture ordering and killer moves heuristic#35

Open
luccabb wants to merge 6 commits intofeature/transposition-table-boundsfrom
feature/mvv-lva-killer-moves
Open

[3/6] Add MVV-LVA capture ordering and killer moves heuristic#35
luccabb wants to merge 6 commits intofeature/transposition-table-boundsfrom
feature/mvv-lva-killer-moves

Conversation

@luccabb
Copy link
Owner

@luccabb luccabb commented Jan 20, 2026

Summary

  • Sort captures by MVV-LVA (Most Valuable Victim - Least Valuable Attacker)
  • Add killer moves heuristic for quiet move ordering
  • Track quiet moves that cause beta cutoffs (2 per ply)

Details

MVV-LVA Capture Ordering

Captures are now sorted by MVV-LVA score, putting the best captures first:

  • Taking a queen with a pawn is searched before taking a pawn with a queen
  • Increases the rate of beta cutoffs, reducing nodes searched

Killer Moves Heuristic

Quiet moves that caused beta cutoffs are remembered:

  • Each ply depth keeps track of 2 killer moves
  • Killers are searched immediately after captures
  • Helps find refutation moves faster in similar positions

Move Ordering Priority

  1. Captures - sorted by MVV-LVA
  2. Killer moves - quiet moves that caused cutoffs at this ply
  3. Other quiet moves - shuffled for variety

Test plan

  • All 64 unit tests pass
  • Verified killer moves are updated on beta cutoffs

🤖 Generated with Claude Code

@luccabb luccabb force-pushed the feature/quiescence-search-improvements branch from e8b9ff6 to df8a32b Compare January 21, 2026 06:40
@luccabb luccabb force-pushed the feature/mvv-lva-killer-moves branch from 0b53062 to 944a0e0 Compare January 21, 2026 06:40
@luccabb luccabb force-pushed the feature/quiescence-search-improvements branch from df8a32b to bfb11c1 Compare January 21, 2026 06:44
@luccabb luccabb force-pushed the feature/mvv-lva-killer-moves branch from 944a0e0 to f1001bf Compare January 21, 2026 06:44
@luccabb luccabb changed the base branch from feature/quiescence-search-improvements to feature/transposition-table-bounds January 21, 2026 07:00
@luccabb luccabb changed the title [5/9] Add MVV-LVA capture ordering and killer moves heuristic [3/7] Add MVV-LVA capture ordering and killer moves heuristic Jan 21, 2026
@luccabb luccabb force-pushed the feature/transposition-table-bounds branch from 4f7fad5 to 1c7b8d9 Compare January 21, 2026 07:33
@luccabb luccabb force-pushed the feature/mvv-lva-killer-moves branch from f1001bf to 98ee9e1 Compare January 21, 2026 07:33
@luccabb luccabb changed the title [3/7] Add MVV-LVA capture ordering and killer moves heuristic [3/6] Add MVV-LVA capture ordering and killer moves heuristic Jan 21, 2026
@luccabb luccabb closed this Jan 27, 2026
@luccabb luccabb reopened this Jan 27, 2026
@luccabb luccabb changed the base branch from feature/transposition-table-bounds to master January 27, 2026 19:32
@luccabb luccabb changed the base branch from master to feature/transposition-table-bounds January 27, 2026 19:34
@github-actions
Copy link

🔬 Stockfish Benchmark Results

vs Stockfish Skill Level 3

Metric Wins Losses Draws Total Win %
Overall 14 85 1 100 14.0%
As White 7 42 1 50 14.0%
As Black 7 43 0 50 14.0%

Non-checkmate endings:

  • Draw by 3-fold repetition: 1

vs Stockfish Skill Level 4

Metric Wins Losses Draws Total Win %
Overall 12 85 3 100 12.0%
As White 7 42 1 50 14.0%
As Black 5 43 2 50 10.0%

Non-checkmate endings:

  • Draw by insufficient mating material: 1
  • Draw by 3-fold repetition: 1

vs Stockfish Skill Level 5

Metric Wins Losses Draws Total Win %
Overall 2 97 1 100 2.0%
As White 2 47 1 50 4.0%
As Black 0 50 0 50 0%

Non-checkmate endings:

  • Draw by insufficient mating material: 1
Configuration
  • 5 chunks × 20 rounds × 3 skill levels = 300 total games
  • Each opening played with colors reversed (-repeat) for fairness
  • Moonfish: 60s per move
  • Stockfish: 60+5 time control

@github-actions
Copy link

🔬 Stockfish Benchmark Results

vs Stockfish Skill Level 3

Metric Wins Losses Draws Total Win %
Overall 7 91 2 100 7.0%
As White 6 42 2 50 12.0%
As Black 1 49 0 50 2.0%

Non-checkmate endings:

  • Draw by fifty moves rule: 1
  • Draw by 3-fold repetition: 1

vs Stockfish Skill Level 4

Metric Wins Losses Draws Total Win %
Overall 11 86 3 100 11.0%
As White 7 41 2 50 14.0%
As Black 4 45 1 50 8.0%

Non-checkmate endings:

  • Draw by 3-fold repetition: 2

vs Stockfish Skill Level 5

Metric Wins Losses Draws Total Win %
Overall 2 96 2 100 2.0%
As White 1 48 1 50 2.0%
As Black 1 48 1 50 2.0%

Non-checkmate endings:

  • Draw by fifty moves rule: 1
  • Draw by 3-fold repetition: 1
Configuration
  • 5 chunks × 20 rounds × 3 skill levels = 300 total games
  • Each opening played with colors reversed (-repeat) for fairness
  • Moonfish: 60s per move
  • Stockfish: 60+5 time control

luccabb and others added 6 commits February 15, 2026 22:30
Improves move ordering for better pruning:

**MVV-LVA (Most Valuable Victim - Least Valuable Attacker):**
- Sort captures by MVV-LVA score in `organize_moves()`
- Best captures (e.g., pawn takes queen) searched first
- Increases beta cutoff rate for better pruning

**Killer Moves Heuristic:**
- Track quiet moves that cause beta cutoffs (2 per ply)
- Add `killers` parameter to `organize_moves()` and `negamax()`
- Killer moves searched after captures, before other quiet moves
- Killers stored in a table indexed by ply depth

**Move Ordering Priority:**
1. Captures (sorted by MVV-LVA)
2. Killer moves (quiet moves that caused cutoffs at this ply)
3. Other quiet moves (shuffled for variety)

Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
@luccabb luccabb force-pushed the feature/mvv-lva-killer-moves branch from 8bab1bf to e73ebd6 Compare February 16, 2026 06:34
@luccabb luccabb force-pushed the feature/transposition-table-bounds branch from fbfac44 to 6912b81 Compare February 16, 2026 06:34
@luccabb
Copy link
Owner Author

luccabb commented Feb 16, 2026

/run-nps-benchmark

@github-actions
Copy link

⚡ NPS Benchmark Results

Metric Value
Depth 5
Positions 48
Total nodes 31699656
Total time 2965.32s
Nodes/second 10690

Node count is the primary signal — it's deterministic and catches search behavior changes. If the node count changes, the PR changed search behavior. NPS is informational only (CI runner performance varies).

Per-position breakdown
Position  1/48: nodes=50546      time=3.69s  nps=13681
Position  2/48: nodes=3479582    time=359.44s  nps=9680
Position  3/48: nodes=6513       time=0.39s  nps=16632
Position  4/48: nodes=1514766    time=152.66s  nps=9922
Position  5/48: nodes=166003     time=18.26s  nps=9090
Position  6/48: nodes=502188     time=50.61s  nps=9923
Position  7/48: nodes=308775     time=28.84s  nps=10706
Position  8/48: nodes=286464     time=22.65s  nps=12649
Position  9/48: nodes=988200     time=78.11s  nps=12651
Position 10/48: nodes=846822     time=76.68s  nps=11043
Position 11/48: nodes=863866     time=92.90s  nps=9299
Position 12/48: nodes=648389     time=59.86s  nps=10831
Position 13/48: nodes=349739     time=30.74s  nps=11375
Position 14/48: nodes=377751     time=34.25s  nps=11028
Position 15/48: nodes=375960     time=28.70s  nps=13100
Position 16/48: nodes=833014     time=71.93s  nps=11581
Position 17/48: nodes=14449      time=0.99s  nps=14592
Position 18/48: nodes=4261       time=0.22s  nps=19804
Position 19/48: nodes=14203      time=1.09s  nps=12987
Position 20/48: nodes=39479      time=2.29s  nps=17214
Position 21/48: nodes=14797      time=0.85s  nps=17380
Position 22/48: nodes=556        time=0.03s  nps=20239
Position 23/48: nodes=4169       time=0.24s  nps=17591
Position 24/48: nodes=9828       time=0.57s  nps=17273
Position 25/48: nodes=10090      time=0.56s  nps=18095
Position 26/48: nodes=52432      time=3.79s  nps=13821
Position 27/48: nodes=128871     time=8.60s  nps=14978
Position 28/48: nodes=635469     time=52.57s  nps=12087
Position 29/48: nodes=81118      time=6.80s  nps=11924
Position 30/48: nodes=1117       time=0.07s  nps=16533
Position 31/48: nodes=943797     time=82.67s  nps=11416
Position 32/48: nodes=1307463    time=115.21s  nps=11348
Position 33/48: nodes=940285     time=115.94s  nps=8110
Position 34/48: nodes=1877969    time=203.71s  nps=9218
Position 35/48: nodes=1037438    time=83.52s  nps=12421
Position 36/48: nodes=7001400    time=677.40s  nps=10335
Position 37/48: nodes=5069942    time=430.05s  nps=11789
Position 38/48: nodes=2396       time=0.11s  nps=21984
Position 39/48: nodes=11198      time=0.40s  nps=27659
Position 40/48: nodes=12236      time=0.22s  nps=55875
Position 41/48: nodes=32999      time=2.14s  nps=15415
Position 42/48: nodes=35709      time=2.24s  nps=15928
Position 43/48: nodes=3977       time=0.20s  nps=19922
Position 44/48: nodes=58484      time=4.36s  nps=13417
Position 45/48: nodes=43661      time=3.30s  nps=13232
Position 46/48: nodes=711285     time=55.46s  nps=12824
Position 47/48: nodes=0          time=0.00s  nps=0  (terminal)
Position 48/48: nodes=0          time=0.00s  nps=0  (terminal)

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant