app/puzzle_led.h

LED highlights while solving a puzzle (lichess-docs/PLAN.md §6, §8).

The puzzle-mode counterpart of LedAssist. It is a separate, much smaller class rather than a reuse of that one, and the reason is the fair-play rule:

LedAssist can show the engine's recommended move. Solving a Lichess puzzle
moves the player's real Lichess puzzle rating, and Lichess forbids engine
assistance — twice, in the Board API docs. So the puzzle path must not be
able to show a hint.

PLAN §8 says that must be structural, not a setting: “the hint path must be

structurally absent, not merely toggled off”. A

showRecommended = false in a config is exactly the kind of thing that gets flipped back on by a later commit that means well. So this class holds no IHintSource, has no setter for one, and never queries the engine at all — the same guarantee PuzzleSession makes by taking no IHintSource in its constructor. It cannot cheat because it has nothing to cheat with, and puzzle_led_test static_asserts as much.

What it does show is what the solver would see on lichess.org: the move that created the tactic, their own correct moves, the board’s replies, and a wrong move flagged in red. Legal-move-on-lift is deliberately absent too — on a rated puzzle, that is help the screen version does not give you either.

Pure: no Qt, no hardware (SimLedDriver in tests). Drives LedController directly.

namespace kirin
class PuzzleLedAssist : public kirin::PuzzleSessionListener
#include <puzzle_led.h>

Public Functions

explicit PuzzleLedAssist(LedController &leds, const LedAssistConfig &config = {})
void setConfig(const LedAssistConfig &config)
inline const LedAssistConfig &config() const
inline void setRenderListener(std::function<void()> onRendered)
virtual void onStateChanged(PuzzleState state) override
virtual void onPuzzleReady(const Puzzle &puzzle, const std::string &lastMove) override
virtual void onCorrectMove(const std::string &uci) override
virtual void onWrongMove(const std::string &uci, const std::string &expected) override
virtual void onReply(const std::string &uci) override
virtual void onPuzzleFinished(const PuzzleResult &result) override

Private Functions

void highlightMove(const std::string &uci, Rgb color)
void clear()
void pushFrame()

Private Members

std::mutex mtx_
LedController &leds_
LedAssistConfig cfg_
std::function<void()> onRendered_
int from_ = -1
int to_ = -1