Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
4 changes: 4 additions & 0 deletions modules/coreI18n/src/main/key.scala
Original file line number Diff line number Diff line change
Expand Up @@ -1651,6 +1651,10 @@ object I18nKey:
val `bestMoveArrow`: I18nKey = "bestMoveArrow"
val `showVariationArrows`: I18nKey = "showVariationArrows"
val `evaluationGauge`: I18nKey = "evaluationGauge"
val `visualMotifs`: I18nKey = "visualMotifs"
val `undefendedPieces`: I18nKey = "undefendedPieces"
val `pinnedPieces`: I18nKey = "pinnedPieces"
val `checkableKing`: I18nKey = "checkableKing"
val `multipleLines`: I18nKey = "multipleLines"
val `cpus`: I18nKey = "cpus"
val `memory`: I18nKey = "memory"
Expand Down
4 changes: 4 additions & 0 deletions translation/source/site.xml
Original file line number Diff line number Diff line change
Expand Up @@ -126,6 +126,10 @@
<string name="bestMoveArrow">Best move arrow</string>
<string name="showVariationArrows">Show variation arrows</string>
<string name="evaluationGauge">Evaluation gauge</string>
<string name="visualMotifs">Visual motifs</string>
<string name="undefendedPieces">Undefended pieces</string>
<string name="pinnedPieces">Pinned pieces</string>
<string name="checkableKing">Checkable king</string>
<string name="multipleLines">Multiple lines</string>
<string name="cpus">CPUs</string>
<string name="memory">Memory</string>
Expand Down
8 changes: 8 additions & 0 deletions ui/@types/lichess/i18n.d.ts
Original file line number Diff line number Diff line change
Expand Up @@ -3211,6 +3211,8 @@ interface I18n {
cheat: string;
/** Cheat Detected */
cheatDetected: string;
/** Checkable king */
checkableKing: string;
/** Check all junk, spam, and other folders */
checkAllEmailFolders: string;
/** Checkmate */
Expand Down Expand Up @@ -4027,6 +4029,8 @@ interface I18n {
perfRatingX: I18nFormat;
/** Piece set */
pieceSet: string;
/** Pinned pieces */
pinnedPieces: string;
/** Play */
play: string;
/** Play against computer */
Expand Down Expand Up @@ -4489,6 +4493,8 @@ interface I18n {
ultraBulletDesc: string;
/** Unblock */
unblock: string;
/** Undefended pieces */
undefendedPieces: string;
/** Unfollow */
unfollow: string;
/** Unfollow %s */
Expand Down Expand Up @@ -4559,6 +4565,8 @@ interface I18n {
viewTheSolution: string;
/** View tournament */
viewTournament: string;
/** Visual motifs */
visualMotifs: string;
/** We will come back to you shortly to help you complete your signup. */
waitForSignupHelp: string;
/** Waiting */
Expand Down
26 changes: 25 additions & 1 deletion ui/analyse/src/autoShape.ts
Original file line number Diff line number Diff line change
Expand Up @@ -3,9 +3,10 @@ import { isDrop } from 'chessops/types';
import { winningChances } from 'lib/ceval';
import { opposite } from '@lichess-org/chessground/util';
import type { DrawModifiers, DrawShape } from '@lichess-org/chessground/draw';
import { annotationShapes } from 'lib/game/glyphs';
import { annotationShapes, analysisGlyphs } from 'lib/game/glyphs';
import type AnalyseCtrl from './ctrl';
import { isUci } from 'lib/game/chess';
import { parseFen } from 'chessops/fen';

const pieceDrop = (key: Key, role: Role, color: Color): DrawShape => ({
orig: key,
Expand Down Expand Up @@ -119,6 +120,29 @@ export function compute(ctrl: AnalyseCtrl): DrawShape[] {
}
if (ctrl.showMoveAnnotationsOnBoard()) shapes = shapes.concat(annotationShapes(ctrl.node));
if (ctrl.showVariationArrows()) hiliteVariations(ctrl, shapes);

if (ctrl.isCevalAllowed()) {
const parsed = parseFen(nFen);
if ('error' in parsed) return shapes;
const { board, epSquare, castlingRights } = parsed.value;

const addAnalysis = (orig: Key, type: keyof typeof analysisGlyphs) => {
const idx = shapes.filter(s => s.orig === orig && s.customSvg).length;
shapes.push({
orig,
customSvg: { html: analysisGlyphs[type](idx) },
});
};

if (ctrl.motifEnabled()) {
ctrl.motif.detectPins(board).forEach(p => addAnalysis(makeSquare(p.pinned) as Key, 'pin'));
ctrl.motif.detectUndefended(board).forEach(u => addAnalysis(makeSquare(u.square) as Key, 'undefended'));
ctrl.motif
.detectCheckable(board, epSquare, castlingRights)
.forEach(s => addAnalysis(makeSquare(s.king) as Key, 'checkable'));
}
}

return shapes;
}

Expand Down
9 changes: 8 additions & 1 deletion ui/analyse/src/ctrl.ts
Original file line number Diff line number Diff line change
Expand Up @@ -47,6 +47,7 @@ import { ChatCtrl } from 'lib/chat/chatCtrl';
import { confirm } from 'lib/view';
import api from './api';
import { displayColumns } from 'lib/device';
import MotifCtrl from './motif/motifCtrl';

export default class AnalyseCtrl implements CevalHandler {
data: AnalyseData;
Expand Down Expand Up @@ -77,6 +78,7 @@ export default class AnalyseCtrl implements CevalHandler {
promotion: PromotionCtrl;
chatCtrl?: ChatCtrl;
wiki?: WikiTheory;
motif: MotifCtrl;

// state flags
justPlayed?: string; // pos
Expand Down Expand Up @@ -140,6 +142,7 @@ export default class AnalyseCtrl implements CevalHandler {
() => this.withCg(g => g.set(this.cgConfig)),
this.redraw,
);
this.motif = new MotifCtrl(this.setAutoShapes);

if (this.data.forecast) this.forecast = new ForecastCtrl(this.data.forecast, this.data, redraw);
if (this.opts.wiki) this.wiki = wikiTheory();
Expand Down Expand Up @@ -651,6 +654,9 @@ export default class AnalyseCtrl implements CevalHandler {
return (this.cevalEnabled() && node.ceval) || (this.showFishnetAnalysis() && node.eval);
}

motifAllowed = (): boolean => this.study?.isCevalAllowed() !== false;
motifEnabled = (): boolean => this.motifAllowed() && this.motif.supports(this.data.game.variant.key);

outcome(node?: Tree.Node): Outcome | undefined {
return this.position(node || this.node).unwrap(
pos => pos.outcome(),
Expand Down Expand Up @@ -1078,7 +1084,8 @@ export default class AnalyseCtrl implements CevalHandler {
if (
this.showBestMoveArrows() ||
this.possiblyShowMoveAnnotationsOnBoard() ||
this.variationArrowOpacity()
this.variationArrowOpacity() ||
(this.motifEnabled() && this.motif.any())
)
this.setAutoShapes();
else this.chessground?.setAutoShapes([]);
Expand Down
Loading
Loading