Conversation
When a position's FEN halfmove clock reaches 100, analysis now shows the fifty-move draw in the engine panel and move-list result, matching threefold handling. Fixes lichess-org#15036
Aybavs
left a comment
There was a problem hiding this comment.
The helper needs the variant. Crazyhouse has no fifty-move rule, Crazyhouse.scala overrides it:
override def fiftyMoves(history: History): Boolean = falseSo isFiftyMoves(fen) calls a draw there that the server doesn't: ceval gets reset, the gauge hides, and the engine panel says "Fifty moves without progress" on a position that isn't drawn. Left a suggestion on the helper. Every call site has a variant handy, d.variant in statusOf, ceval.opts.variant.key in renderCeval, root.variantKey in the analyse and practice files.
Two other things I noticed:
renderResult: with a study this only fires when a relay has "show results" off, so it shows a result to someone who asked not to see one. !ctrl.study && covers it.
ctrl.ts imports isFiftyMoves from lib/game and plyColor from lib/game/chess, same file.
All of it is one commit on top of your branch if you want to take it: Aybavs@5fbaa20. Call sites updated, and the tests moved to ui/lib/tests/chess.test.ts with the variant cases added. The crazyhouse one fails on your current version and passes after.
| // FIDE fifty-move rule: 100 halfmoves in the FEN clock. | ||
| export function isFiftyMoves(fen: FEN): boolean { | ||
| const halfmoves = Number(fen.split(' ')[4]); | ||
| return Number.isFinite(halfmoves) && halfmoves >= 100; | ||
| } |
There was a problem hiding this comment.
| // FIDE fifty-move rule: 100 halfmoves in the FEN clock. | |
| export function isFiftyMoves(fen: FEN): boolean { | |
| const halfmoves = Number(fen.split(' ')[4]); | |
| return Number.isFinite(halfmoves) && halfmoves >= 100; | |
| } | |
| // crazyhouse has no fifty-move rule, as in scalachess | |
| export const isFiftyMoves = (variant: VariantKey, fen: FEN): boolean => | |
| variant !== 'crazyhouse' && Number(fen.split(/\s/)[4]) >= 100; |
Number.isFinite isn't needed, a FEN with no halfmove clock already gives NaN and NaN >= 100 is false.
There was a problem hiding this comment.
Applied this. isFiftyMoves now takes the variant and returns false for crazyhouse, matching scalachess Crazyhouse.fiftyMoves = false. Number.isFinite is gone.
Also on the same follow-up: renderResult is gated with !ctrl.study, and the ctrl.ts imports are consolidated onto lib/game/chess.
Crazyhouse overrides fiftyMoves to false in scalachess, so a FEN-only check was calling a draw the server does not. Studies with results hidden also fell through to the synthetic 1/2-1/2 line. Tests live in ui/lib/tests/chess.test.ts.
A mate with halfmove clock 100 was shown as a fifty-move draw in the move list and practice box. isFiftyMoveDraw requires no board outcome first, matching scalachess status order.
|
Ran a local Codex review with GPT-5.6-Sol. Sol agreed with @Aybavs (crazyhouse, study results, imports) and found one extra bug: a checkmate (or stalemate) with halfmove clock 100 was still shown as a fifty-move draw in Fixed in |
|
GPT-5.6-Sol re-reviewed No remaining bugs. Checkmate/stalemate at clock 100 now wins over the fifty-move label; crazyhouse stays excluded; studies still do not get a synthetic result. |
Aybavs
left a comment
There was a problem hiding this comment.
Looks right to me.
Checked the mate case: for 7k/6Q1/5K2/8/8/8/8/8 b - - 100 50 the predicate was true before c521758 and the practice box said "Draw / Fifty moves", now it says "Checkmate / white wins". The call sites still on the raw isFiftyMoves all test outcome() first, so nothing left there.
Minor: chessops exports Outcome, so outcome: Outcome | undefined would do instead of the inline shape, and | null never comes out of node.outcome().
I only ran the tests and tsc on your branch though, no local lila, so none of this has been seen in a browser yet.
8f6e873 to
b7598c4
Compare
|
You removed the draft status. Have you tried the changes in a browser? Have you reproduced the original issue? |
When did I do that? I will try to set it up. Still had some troubles on how to exactly do that. Any best practices? I will write you if I set it up; might take a week and then I will show you screenshot. |
Fixes #15036
When analysing a position that has already hit the fifty-move rule (FEN halfmove clock >= 100), the UI gave no reason for the draw. Threefold already shows in the engine panel; fifty-move did not.
Changes
isFiftyMoves(fen)helper (100+ halfmoves, not only exactly 100)-and "Fifty moves without progress", same as threefoldTesting
ui/lib/tests/status.test.tsfor 0 / 99 / 100 / 150 / incomplete FENAI disclosure
This work was produced by Grok 4.6 (xAI Grok Build CLI), an AI coding agent, on behalf of this GitHub account.
Prompts used:
I reviewed the existing threefold-repetition handling and mirrored that path for fifty-move. I did not generate tests without reading the analysis/ceval code first.