Skip to content

Releases: lynx-chess/Lynx

v1.7.0

04 Oct 22:18
Compare
Choose a tag to compare

πŸ” Search

  • Regular search: fail hard -> fail soft (#1039, #1040, #1041)
  • QSearch: fail hard -> fail soft (#1052)
  • Fail soft TT cutoffs (#1044)
  • Remove pvNode condition for first move full search (#1045)
  • History pruning: quiet history (#972)
  • Improve queen promotion with capture move ordering (#1061)
  • Make TranspositionTableElement.Key an ushort instead of a short (#1070)
  • SPSA 2024-10-1 (#1074)

βš–οΈ Evaluation

  • Enemy king related PSQTs (#924)
  • Friendly and enemy king distance to passed pawn (#955)
  • Passed pawns: bonus for not enemy pieces ahead (#998, #1008)
  • Pawn phalanx (#1009, #1010)
  • Bishop penalty: same color pawns (#1022)
  • Bishop penalty: blocked central pawns (#1029)
  • Checks (#1027)
  • Mobility: exclude squares attacked by opponent's pawn (#958)
  • Add 50 moves rule scaling, down to 50% of the score (#965)
  • Improve endgame scaling with pawn count (#928)
  • Bucketed passed pawns (#945)
  • Index queen mobility bonus by attacks count excluding own pieces (#774)
  • Tuning: use some Ethereal FRC data (#916)
  • Tuning: tune at 5k epochs (50k epochs -> 10k epochs -> 5k) epochs (#1031)

βŒ› Time management

  • Use expected moves to go (#996)

⚑ Speedups

  • Move Move serialization to Writer thread (#999)
  • Add a Board array to Position to track where pieces are indexed by square (#849)
  • Remove good old _isFollowingPV and _isScoringPV (#1034)
  • Make TaperedEvaluationTerm an integer I (#935)
  • Add PSQT class to store PackedPSQT (#939)
  • Flatten PSQTs [][][][] (#927)
  • Flatten capture history (#870)
  • Pin 1 dimension arrays (#953)
  • Pin attack-related arrays (#985)
  • Reverse killer moves arrays (#861)
  • Replace Chebyshev distance calculation with lookup table (double array) (#957)
  • Refactor additional evaluations: pass piece side (#963)
  • Speedup InfoCommand.SearchResultInfo (#984)
  • Make SearchResult.Moves an array and optimize its population (#986)
  • Refactor Game.PositionHashHistory into a private array (#991)
  • Remove Position.MakeMoveCalculatingCapturedPiece, using Position.Board instead (#1021)
  • Only update PV table on PV nodes (#1042)

🧠 Memory usage (!)

  • Remove unnecessary, initial TT initializations (#989)
  • Allocate TT only once, clearing it afterwards on ucinewgame (#990)
  • Avoid static readonly flat array initial allocations for inline arrays (#948)
  • Use ArrayPool to reduce recurrent allocations (#983)
  • Stop generating logs/log-βˆ—.log files by default (#1004)
  • Cache Move.UCIString results in a Dictionary(#1001)
  • Optimize go command parsing (#1005)
  • Remove unused props from SearchResult and re-order the ones left (#1006)

πŸ› Bug fixes

  • Don't prune moves in regular search while being checkmated (#1060)
  • Prevent negative checkmate scores from being lower than EvaluationConstants.MinEval (#1063)

Non-strength winning changes:

Relevant for testers:

  • By default log files are no longer generated under logs/ dir unless warnings or errors happen (#1004)
  • Lynx process' memory usage won't skyrocket to twice the expected (TT) value anymore, as it could briefly happen in the past, providing there was such memory available for it.
  • Simplify appsettings.json (#1075)

Relevant for developers that consume the NuGet package:

  • Lynx allocates way less than before when searching, which implies much lower GC pressure.
  • You have control now of UCI info and bestmove string allocations if you're using Searcher class to interact with the engine, since now the channel doesn't send the information pre-serialized (details below).
  • API changes:
    • Channel<string> -> Channel<object>, you're now expected to invoke .ToString() on whatever comes from the channel to print it. Alternatively, you can just consume it by checking object types (they are either strings, Lynx.Model.SearchResult or Lynx.UCI.Commands.Engine.BestMoveCommand) (#999)
    • Remove Position(Position, Move) constructors, now you're forced to use MakeMove/UnMakeMove methods (#976)
    • Remove parameterless Game constructor, a fen or a parsing result is always required now (tip: Constants.InitialPositionFEN can be used) (#980)
    • Make Position.UniqueIdentifier an ulong instead of a long (#1078)

Full Changelog: v1.6.0...v1.7.0

v1.6.0

15 Aug 00:18
Compare
Choose a tag to compare
  • πŸ” Countermoves (#859)
  • πŸ” Continuation history - countermove history (1 ply) (#645)
  • πŸ” Don't always stop search when a mate is found (#827)
  • πŸ” SPSA 2024-6-27 (#839)
  • βš–οΈ King-bucketed PSQTs (#873 (2) -> #876 (8) -> #879 + #888 (16) -> #893 (24) -> #902 (23))
  • βš–οΈ Escale endgame eval with pawn count (#821, #829)
  • βš–οΈ Give bonus to pieces protected by friendly pawns and penalty to pieces attacked by opponent pawns (#830)
  • βš–οΈ Use some Pedantic data for HCE tuning (#905)
  • ⚑ Avoid stackalloc local initialization when allocating it for movegen (#858)
  • ⚑ Optimize MoveGenerator.GeneratePieceCaptures() (#846)
  • ⚑ Micro-optimization in MoveGenerator.IsAnyPieceMoveValid (#845)

Non strength-winning changes:

  • βš™οΈ Move eval parameters out of Configuration class, making them no longer configurable via appsettings.json (#889, #911)
  • πŸ› Make .ToEPDString() fully PGN/EPD compliant (#841)
  • πŸ› Avoid node count overflow (#835)

Full Changelog: v1.5.1...v1.6.0

v1.5.1

21 Jun 09:39
Compare
Choose a tag to compare
  • πŸ› Threefold repetition bugfix: Revert "Detect threefold repetition on pvNode (#796)" (#818)

Full Changelog: v1.5.0...v1.5.1

v1.5.0

09 Jun 00:16
Compare
Choose a tag to compare
  • πŸ” Add Futility pruning (FP) (#733)
  • πŸ” LMR: allow when in check (#702)
  • πŸ” LMR: reduce more if there's a TT move and a capture (#706)
  • πŸ” Move RFP before NMP (#732)
  • πŸ” SPSA search parameters tuning (#730, #764)
  • βš–οΈ Remove double pawns penalty [proper SPRT pawn eval] (#746)
  • βš–οΈ Index bishop mobility bonus by attacks count (#758)
  • βš–οΈ Index rook mobility bonus by attacks count exluding own pieces (#768)
  • βš–οΈ Add knight mobility bonus and index it by attacks count excluding own pieces (#775)
  • βš–οΈ Take only pawns into account for king shield (#789)
  • βš–οΈ Add king virtual mobility indexed by mobility count (#785)
  • βš–οΈ Use some Stoofvlees quiet data for eval tuning (#710)
  • ⚑ Improve search logic (#725)
  • ⚑ Use optimized method to check if a move was valid (#716)
  • ⚑ Use a StringBuilder to generate UCI info command (#805)
  • ⚑ Remove option to disable TT (#720)
  • ⚑ Remove manual piece count during static eval (#698)
  • ⚑ Simplify TaperedEvaluationTermByRank (#757)
  • ⚑ Simplify TaperedEvaluationTermByCount (#767)
  • ⚑ Simplify Aspiration windows (#802)
  • πŸ› Fix index out of range exception on max depth (#708)
  • πŸ› Detect threefold repetition on pvNode (#796)
  • πŸ› Fix Game.MakeMove behavior on invalid moves (#804)

Non strength-winning changes:

  • Add ponder support (#772)
  • Generate UCI options for search parameters dynamically (#734)
  • Normalize mobility values (#788)

Full Changelog: v1.4.0...v1.5.0

v1.4.0

21 Mar 11:38
Compare
Choose a tag to compare
  • πŸ” Improve RFP (#652)
  • πŸ” Avoid doing TT cutoffs on PV nodes (#653)
  • πŸ” Use TT score as positional eval for pruning (#692)
  • βš– Tweak pawnless endgames evaluation (#693)
  • βŒ› Tweak time management (#664, #665, #667, #668, #671, #677, #691)
  • ⚑ Stop checking for two/threefold repetition and 50 moves draws in QSearch (#673)
  • ⚑ Refactor Update50movesRule() method (#678)
  • ⚑ Reimplement repetition detection (#679)
  • ⚑ Prefetch TT entry in NegaMax search (#681)
  • ⚑ Remove Position.StaticEval() heap allocations (#683)
  • ⚑ Force GC collection at the end of Engine constructor and after ucinewgame (#685)
  • ⚑ Use packed evaluation (#697)
  • πŸ› Clear history on newgame (#649)
  • πŸ› Fix long input position commands parsing (#650)
  • πŸ› Fix engine stall when depth over 100 is reached during search (#651)
  • πŸ› Don't search with fixed depth when cutechess provides 0s to move (#654)
  • πŸ› Prevent illegal moves when low in time (#657)
  • πŸ› Error when searching at max depth (#670)

Non strength-winning changes:

  • Add fen UCI command (#688
  • Increase max TT size from 1GB to 8GB (#669)
  • πŸ› Fix behavior of consecutive go commands (#655)

Full Changelog: v1.3.0...v1.4.0

v1.3.0

04 Feb 22:17
Compare
Choose a tag to compare
  • πŸ” Add basic (quiet) history malus/penalty (#610)
  • πŸ” Add capture history (#634)
  • πŸ” Update (quiet) history moves only in beta cutoffs (#608)
  • πŸ” Stop clearing quiet history (#637)
  • πŸ” Take quiet history into consideration for LMR (#613)
  • ⚑ Refactor move encoding methods and stop encoding special move flags individually (#622)
  • ⚑ Store captured pieces as part of the move (#604)
  • ⚑ Use jagged arrays ([][]) instead of multidimensional ones ([,]) (#605, #606, #607)
  • ⚑ Simplify triple repetition detection logic, removing some branching (#623)
  • ⚑ Make Piece an integer enum (#603)

Full Changelog: v1.2.0...v1.3.0

v1.2.0

11 Jan 14:52
Compare
Choose a tag to compare
  • πŸ” Prune SEE bad captures in QSearch (#558)
  • πŸ” Reduce SEE bad captures in regular search (#564, #571)
  • πŸ” Use spsa tuned search values (#543, #553)
  • βš–οΈ Add rook mobility to eval (#539)
  • 🧬 Improve move generation: hardcode castling moves and a few calculated variables (#541)
  • 🧬 Implement SEE and order bad captures after killers but before quiet moves (#554)
  • ⚑ Reduce TT entry size to 8 bytes (#544)
  • ⚑ Optimize go command parsing (#545)
  • ⚑ Split MoveGenerator.GenerateAllMoves and MoveGenerator.GenerateCaptures to avoid branching (#549)
  • ⚑ Set search thread as high priority (#546)
  • ⚑ SEE micro-optimizations (#566)
  • ⚑ Use stack-allocated span for movegen (#551, #596)
  • ⚑ Optimize PositionHash (#582)
  • ⚑ Optimize castling and en-passant moves Zobrist hashing (#577)
  • ⚑ Replace EnPassantCaptureSquares dictionary with equivalent array (#578)
  • ⚑ Optimize FEN parsing (#581)
  • ⚑ Attempt to initialize MoveGenerator and GoCommand asap (#576)
  • πŸ› Fix engine crash due to a negative calculated time to move (#555)
  • πŸ› Add support for negative wtime and btime (#556)
  • πŸ› Enable InvariantGlobalization and fix crash in some Linux scenarios (#575)

Non strength-winning changes:

  • Add option to run bench at different depths (#537)

Full Changelog: v1.1.0...v1.2.0

v1.1.0

14 Dec 00:49
Compare
Choose a tag to compare
  • πŸ” Add Internal Iterative Reduction (IIR) (#507)
  • πŸ” Add basic LMP (#512)
  • πŸ” Improve TT replacement scheme: add required conditions for always replace (#526)
  • πŸ” Add third killer move (#517, #525)
  • πŸ” Use new history bonus formula based on Sirius and Berserk one (#527)
  • πŸ” In case of 'fake' ponder-hit, research from depth 1 (#467)
  • βš– Re-tune eval using some Stash data (#515)
  • ⚑ Avoid PEXT array initialization when PEXT isn't supported (#516)

Full Changelog: v1.0.1...v1.1.0

v1.0.1

20 Nov 09:48
Compare
Choose a tag to compare

Non strength-winning changes:

  • πŸ› Clamp static evaluation within +- checkmate limits, preventing illegal moves (and erratic behavior in general) in positions with too much material on one side (#510).

    We're talking about positions here such as QQQQQQQQ/QQQQQQQQ/QQQQQQQQ/QQQQQQQQ/QQQQQQQQ/QQQQQQQQ/QPPPPPPP/K6k b - - 0 1, which will never happen in a real game but can be artificially set up (i.e. in lichess), so no strength change is expected in regular engine games.


Full Changelog: v1.0.0...v1.0.1

v1.0.0

16 Nov 12:16
Compare
Choose a tag to compare

Getting out from ZeroVer club now that these two conditions are met:

  • Lynx has basically reached feature-parity with BBC, engine outcome of BitBoard Chess Engine in C YouTube playlist that helped me the most during the initial phases of Lynx development.
  • .NET 8 GA has been released and therefore Lynx no longer relies on pre-release SDK or library versions.

  • πŸ” Rewrite NMP (#479, #482, #492, #493, #494)
  • πŸ” In case of 'ponder-hit', research last depth (#466)
  • πŸ” Don't clear TT move if no best move is provided: keep old one II (#478)
  • βš– Use PSQTs tuned without explicit piece values (#425)
  • ⚑ Incremental move sorting (#477)
  • ⚑ Avoid checking lack of material in static evaluation when the phase is high enough (#490)

Full Changelog: v0.19.0...v1.0.0