chesspal 0.1.0 → 0.2.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/README.md +45 -82
- package/dist/cli/chat-hook.js +1 -1
- package/dist/cli/command-line.d.ts +1 -2
- package/dist/cli/command-line.js +2 -3
- package/dist/commands/agents.d.ts +26 -0
- package/dist/commands/agents.js +72 -0
- package/dist/commands/ai-move.d.ts +5 -14
- package/dist/commands/ai-move.js +28 -35
- package/dist/commands/ai-say.d.ts +3 -1
- package/dist/commands/ai-say.js +24 -6
- package/dist/commands/analyse-game.d.ts +4 -0
- package/dist/commands/analyse-game.js +43 -16
- package/dist/commands/annotate-game.d.ts +4 -0
- package/dist/commands/annotate-game.js +65 -12
- package/dist/commands/answer-lines.d.ts +28 -0
- package/dist/commands/answer-lines.js +144 -0
- package/dist/commands/coach.d.ts +45 -0
- package/dist/commands/coach.js +344 -0
- package/dist/commands/context.d.ts +16 -5
- package/dist/commands/context.js +1 -0
- package/dist/commands/delete-game.d.ts +7 -0
- package/dist/commands/delete-game.js +30 -0
- package/dist/commands/delete-review.d.ts +8 -0
- package/dist/commands/delete-review.js +34 -0
- package/dist/commands/drawings.d.ts +0 -2
- package/dist/commands/drawings.js +5 -3
- package/dist/commands/end-game.js +5 -2
- package/dist/commands/export-game.d.ts +1 -1
- package/dist/commands/export-game.js +4 -3
- package/dist/commands/game-summary.d.ts +21 -38
- package/dist/commands/game-summary.js +30 -167
- package/dist/commands/index.d.ts +15 -0
- package/dist/commands/index.js +47 -2
- package/dist/commands/init.d.ts +3 -3
- package/dist/commands/init.js +4 -4
- package/dist/commands/lead-input.d.ts +8 -0
- package/dist/commands/lead-input.js +21 -0
- package/dist/commands/look.js +4 -1
- package/dist/commands/new-game.d.ts +2 -3
- package/dist/commands/new-game.js +7 -4
- package/dist/commands/play-move.d.ts +8 -15
- package/dist/commands/play-move.js +5 -13
- package/dist/commands/player-move.d.ts +2 -6
- package/dist/commands/player-move.js +13 -6
- package/dist/commands/player-say.d.ts +1 -1
- package/dist/commands/player-say.js +1 -1
- package/dist/commands/ponder.d.ts +10 -0
- package/dist/commands/ponder.js +33 -21
- package/dist/commands/position.d.ts +1 -1
- package/dist/commands/position.js +3 -1
- package/dist/commands/profiles.d.ts +13 -4
- package/dist/commands/profiles.js +49 -15
- package/dist/commands/registry.d.ts +8 -3
- package/dist/commands/registry.js +12 -11
- package/dist/commands/say.d.ts +1 -1
- package/dist/commands/say.js +16 -16
- package/dist/commands/speech.d.ts +8 -0
- package/dist/commands/speech.js +20 -0
- package/dist/commands/status.d.ts +9 -3
- package/dist/commands/status.js +40 -15
- package/dist/commands/study-games.js +1 -1
- package/dist/commands/study.js +3 -19
- package/dist/core/facts.js +15 -15
- package/dist/core/game.d.ts +3 -1
- package/dist/core/game.js +8 -4
- package/dist/core/illegal.js +1 -1
- package/dist/core/index.d.ts +5 -4
- package/dist/core/index.js +5 -4
- package/dist/core/lead.d.ts +15 -0
- package/dist/core/lead.js +40 -0
- package/dist/core/levels.d.ts +1 -1
- package/dist/core/levels.js +1 -1
- package/dist/core/moods.d.ts +0 -2
- package/dist/core/moods.js +2 -2
- package/dist/core/openings.d.ts +0 -2
- package/dist/core/openings.js +1 -1
- package/dist/core/profile.js +1 -1
- package/dist/core/record.d.ts +1 -1
- package/dist/core/record.js +1 -1
- package/dist/core/review.d.ts +9 -3
- package/dist/core/review.js +29 -9
- package/dist/games/analysis.d.ts +1 -1
- package/dist/games/archive.d.ts +24 -3
- package/dist/games/archive.js +96 -22
- package/dist/games/coach.d.ts +57 -0
- package/dist/games/coach.js +144 -0
- package/dist/games/current-game.d.ts +2 -0
- package/dist/games/current-game.js +7 -1
- package/dist/games/files.js +1 -0
- package/dist/games/index.d.ts +4 -3
- package/dist/games/index.js +4 -3
- package/dist/games/talk.d.ts +1 -5
- package/dist/games/talk.js +14 -14
- package/dist/home/open-folder.js +1 -1
- package/dist/host-files/{ponder-agents.d.ts → agents.d.ts} +10 -2
- package/dist/host-files/agents.js +53 -0
- package/dist/host-files/host-files.d.ts +7 -2
- package/dist/host-files/host-files.js +27 -12
- package/dist/host-files/index.d.ts +2 -2
- package/dist/host-files/index.js +3 -3
- package/dist/index.d.ts +1 -3
- package/dist/index.js +1 -0
- package/dist/page/app/anchor.js +88 -0
- package/dist/page/{app.js → app/app.js} +112 -230
- package/dist/page/app/keys.js +94 -0
- package/dist/page/app/phase.js +30 -0
- package/dist/page/app/served.js +73 -0
- package/dist/page/avatars/avatars.js +19 -0
- package/dist/page/avatars/thought.js +10 -0
- package/dist/page/base.css +160 -0
- package/dist/page/board/board.css +959 -0
- package/dist/page/board/board.js +125 -0
- package/dist/page/{explain.js → board/explain.js} +1 -1
- package/dist/page/board/marks.js +160 -0
- package/dist/page/board/motion.js +71 -0
- package/dist/page/board/pointer.js +239 -0
- package/dist/page/board/squares.js +26 -0
- package/dist/page/dialogs/analyses.js +195 -0
- package/dist/page/{dialog.js → dialogs/dialog.js} +1 -1
- package/dist/page/dialogs/dialogs.css +1228 -0
- package/dist/page/{new-game-dialog.js → dialogs/new-game.js} +3 -3
- package/dist/page/{profile-dialogs.js → dialogs/profiles.js} +40 -11
- package/dist/page/dialogs/search.js +31 -0
- package/dist/page/dialogs/settings.js +42 -0
- package/dist/page/dialogs/studied.js +39 -0
- package/dist/page/dialogs/study.js +51 -0
- package/dist/page/{badges.js → game/badges.js} +1 -1
- package/dist/page/{browse.js → game/browse.js} +1 -1
- package/dist/page/game/card-fold.js +40 -0
- package/dist/page/game/column.js +51 -0
- package/dist/page/{ending.js → game/ending.js} +2 -2
- package/dist/page/game/game.css +577 -0
- package/dist/page/{move-list.js → game/move-list.js} +10 -6
- package/dist/page/{plies.js → game/plies.js} +30 -10
- package/dist/page/game/result-tile.js +14 -0
- package/dist/page/helps/helps.css +689 -0
- package/dist/page/helps/helps.js +220 -0
- package/dist/page/helps/view.js +127 -0
- package/dist/page/layout/fold-tab.js +11 -0
- package/dist/page/{folds.js → layout/folds.js} +1 -1
- package/dist/page/{header.js → layout/header.js} +5 -4
- package/dist/page/layout/layout.css +834 -0
- package/dist/page/lead/lead.js +82 -0
- package/dist/page/lead/view.js +38 -0
- package/dist/page/main.js +2 -2
- package/dist/page/pieces/CREDITS.md +12 -29
- package/dist/page/pieces/capablanca-small.svg +20 -0
- package/dist/page/pieces/capablanca.svg +22 -0
- package/dist/page/pieces/nitida-small.svg +3 -2
- package/dist/page/pieces/nitida.svg +3 -2
- package/dist/page/{pieces.js → pieces/pieces.js} +2 -2
- package/dist/page/pieces/torretta-small.svg +15 -14
- package/dist/page/pieces/torretta.svg +17 -15
- package/dist/page/{player-card.js → players/card.js} +2 -6
- package/dist/page/{clock-time.js → players/clock-time.js} +2 -2
- package/dist/page/{profile.js → profile/profile.js} +9 -5
- package/dist/page/{settings.js → profile/settings.js} +5 -4
- package/dist/page/style.css +9 -4398
- package/dist/page/talk/talk.css +958 -0
- package/dist/page/{talk.js → talk/talk.js} +39 -46
- package/dist/page/text.js +137 -19
- package/dist/page/theme.css +292 -0
- package/dist/profiles/index.d.ts +1 -1
- package/dist/profiles/profiles.d.ts +15 -4
- package/dist/profiles/profiles.js +24 -7
- package/dist/server/bell.d.ts +10 -2
- package/dist/server/bell.js +28 -12
- package/dist/server/caller.d.ts +14 -3
- package/dist/server/caller.js +44 -11
- package/dist/server/mcp.d.ts +1 -2
- package/dist/server/mcp.js +42 -14
- package/dist/server/page/analyses.d.ts +23 -0
- package/dist/server/page/analyses.js +65 -0
- package/dist/server/page/files.d.ts +5 -0
- package/dist/server/page/files.js +92 -0
- package/dist/server/page/game.d.ts +6 -0
- package/dist/server/page/game.js +381 -0
- package/dist/server/{http.d.ts → page/http.d.ts} +13 -0
- package/dist/server/{http.js → page/http.js} +11 -0
- package/dist/server/{page.d.ts → page/page.d.ts} +8 -13
- package/dist/server/page/page.js +229 -0
- package/dist/server/{profile-routes.d.ts → page/profiles.d.ts} +2 -2
- package/dist/server/{profile-routes.js → page/profiles.js} +47 -18
- package/instructions/analysis.md +4 -0
- package/instructions/analyst-agent.md +8 -0
- package/instructions/analyst.md +3 -7
- package/instructions/coach.md +11 -0
- package/instructions/opponent.md +4 -4
- package/package.json +1 -1
- package/dist/host-files/ponder-agents.js +0 -40
- package/dist/page/avatars.js +0 -16
- package/dist/page/board.js +0 -566
- package/dist/page/fold-tab.js +0 -9
- package/dist/page/game-column.js +0 -44
- package/dist/page/helps-view.js +0 -51
- package/dist/page/helps.js +0 -90
- package/dist/page/pieces/cburnett-small.svg +0 -20
- package/dist/page/pieces/cburnett.svg +0 -20
- package/dist/page/settings-panel.js +0 -32
- package/dist/page/studied.js +0 -14
- package/dist/page/study-dialog.js +0 -58
- package/dist/server/analyses.d.ts +0 -17
- package/dist/server/analyses.js +0 -46
- package/dist/server/page.js +0 -657
- /package/dist/page/{torretta.js → avatars/torretta.js} +0 -0
- /package/dist/page/{opening-book.js → game/opening-book.js} +0 -0
- /package/dist/page/{model-name.js → players/model-name.js} +0 -0
- /package/dist/page/{sounds.js → sounds/sounds.js} +0 -0
- /package/dist/page/{voice.js → talk/voice.js} +0 -0
|
@@ -1,5 +1,6 @@
|
|
|
1
1
|
import { z } from "zod";
|
|
2
|
-
import { type GameSummary
|
|
2
|
+
import { type GameSummary } from "./game-summary.ts";
|
|
3
|
+
import { type Speech } from "./speech.ts";
|
|
3
4
|
interface Status {
|
|
4
5
|
version: string;
|
|
5
6
|
folder: string;
|
|
@@ -14,15 +15,20 @@ interface Status {
|
|
|
14
15
|
game?: GameSummary;
|
|
15
16
|
/** Why the game on disk cannot be read, when it cannot. */
|
|
16
17
|
problem?: string;
|
|
17
|
-
/** What the player wrote on the board page that the AI has not answered yet, all of it
|
|
18
|
+
/** What the player wrote on the board page that the AI has not answered yet, all of it. */
|
|
18
19
|
words?: string[];
|
|
19
|
-
/** The game in analysis on the board page once none goes on (D-69), which the player may have brought there
|
|
20
|
+
/** The game in analysis on the board page once none goes on (D-69), which the player may have brought there. */
|
|
20
21
|
analysis?: {
|
|
21
22
|
game: string;
|
|
22
23
|
brought?: true;
|
|
24
|
+
analyst?: true;
|
|
23
25
|
};
|
|
24
26
|
/** A game going on from before this chat, told once a chat: the player says whether to go on with it. */
|
|
25
27
|
fromBefore?: true;
|
|
28
|
+
/** The coach to start, once, for the player's move that ended the game (D-88). */
|
|
29
|
+
coach?: true;
|
|
30
|
+
/** The files an older init wrote in the player's folder, which this version would write otherwise. */
|
|
31
|
+
outdated?: string[];
|
|
26
32
|
}
|
|
27
33
|
/** What Chesspal sees now, the first call of a chat: a dashboard under 150 tokens while the player is to move, with the next step. */
|
|
28
34
|
export declare const status: import("./registry.ts").Command<z.ZodObject<{}, z.core.$strip>, Status>;
|
package/dist/commands/status.js
CHANGED
|
@@ -1,14 +1,18 @@
|
|
|
1
1
|
import { z } from "zod";
|
|
2
2
|
import { archivedName, cleanSince, endOf, gameInAnalysis, lastChatStart } from "../games/index.js";
|
|
3
|
+
import { coachAgent, outdatedHostFiles } from "../host-files/index.js";
|
|
3
4
|
import { gameFolder } from "../profiles/index.js";
|
|
4
5
|
import { version } from "../version.js";
|
|
6
|
+
import { agentsLine, analystLine, analystRuns, coachOnEnd, coachRuns, reviewedLine, withAnalyst } from "./agents.js";
|
|
7
|
+
import { closingLines, newGameStep, positionLines, sidesLine, wordLines } from "./answer-lines.js";
|
|
5
8
|
import { gameAt } from "./clock.js";
|
|
6
|
-
import {
|
|
9
|
+
import { summaryOf, withThought } from "./game-summary.js";
|
|
7
10
|
import { levelText } from "./levels.js";
|
|
8
11
|
import { closedPage, pageGiven, pageLine } from "./page-link.js";
|
|
9
12
|
import { playerLine } from "./profiles.js";
|
|
10
13
|
import { defineCommand } from "./registry.js";
|
|
11
14
|
import { unansweredWords } from "./say.js";
|
|
15
|
+
import { speechLine, speechOf } from "./speech.js";
|
|
12
16
|
/** What Chesspal sees now, the first call of a chat: a dashboard under 150 tokens while the player is to move, with the next step. */
|
|
13
17
|
export const status = defineCommand({
|
|
14
18
|
name: "status",
|
|
@@ -19,12 +23,13 @@ export const status = defineCommand({
|
|
|
19
23
|
readOnly: true,
|
|
20
24
|
alwaysLoad: true,
|
|
21
25
|
showsGame: true,
|
|
22
|
-
run: (
|
|
26
|
+
run: (input, context) => {
|
|
23
27
|
// The folder is the profile's, in the data folder (D-71): the names of its games are relative to it.
|
|
24
28
|
const folder = gameFolder(context.home());
|
|
25
29
|
const player = playerLine(context);
|
|
26
30
|
const speech = speechOf(folder, context.language);
|
|
27
|
-
const
|
|
31
|
+
const outdated = outdatedHostFiles(context.folder, context.platform);
|
|
32
|
+
const status = { version, folder, ...(player === undefined ? {} : { player }), ...(speech === undefined ? {} : { speech }), ...(outdated.length === 0 ? {} : { outdated }) };
|
|
28
33
|
if (context.page !== undefined) {
|
|
29
34
|
status.page = context.page;
|
|
30
35
|
}
|
|
@@ -40,17 +45,22 @@ export const status = defineCommand({
|
|
|
40
45
|
status.words = words;
|
|
41
46
|
}
|
|
42
47
|
if (current !== undefined) {
|
|
43
|
-
status.game = withThought(summaryOf(current, context.now(), archivedName(folder, current)), folder, current);
|
|
48
|
+
status.game = withAnalyst(withThought(summaryOf(current, context.now(), archivedName(folder, current)), folder, current, coachRuns(context)), context, current);
|
|
44
49
|
if (status.pageClosed === true) {
|
|
45
50
|
pageGiven(context, current.started);
|
|
46
51
|
}
|
|
47
52
|
if (first && endOf(current.game) === undefined && fromBeforeChat(context, current.started)) {
|
|
48
53
|
status.fromBefore = true;
|
|
49
54
|
}
|
|
55
|
+
// The player's move on the board page that ended the game: the coach judges it too (D-88).
|
|
56
|
+
if (coachOnEnd(context, folder, current)) {
|
|
57
|
+
status.coach = true;
|
|
58
|
+
}
|
|
50
59
|
}
|
|
51
60
|
const analysis = current === undefined || status.game?.end !== undefined ? gameInAnalysis(folder) : undefined;
|
|
52
61
|
if (analysis !== undefined) {
|
|
53
|
-
|
|
62
|
+
// The analyst agent goes over a game the player brought, where it runs, and the chat over what it reviewed (D-89).
|
|
63
|
+
status.analysis = { game: analysis.game, ...(analysis.brought === true ? { brought: true } : {}), ...(analystRuns(context) ? { analyst: true } : {}) };
|
|
54
64
|
}
|
|
55
65
|
}
|
|
56
66
|
catch (error) {
|
|
@@ -58,16 +68,22 @@ export const status = defineCommand({
|
|
|
58
68
|
}
|
|
59
69
|
return status;
|
|
60
70
|
},
|
|
61
|
-
format: ({ version, folder, page, pageClosed, player, speech, game, problem, words = [], analysis, fromBefore }) => [
|
|
71
|
+
format: ({ version, folder, page, pageClosed, player, speech, game, problem, words = [], analysis, fromBefore, coach, outdated }) => [
|
|
62
72
|
`Chesspal ${version}. Folder: ${folder}`,
|
|
73
|
+
...(outdated === undefined ? [] : [outdatedLine(outdated)]),
|
|
63
74
|
...(page === undefined ? [] : [pageLine(page, pageClosed === true)]),
|
|
64
75
|
...(player === undefined ? [] : [player]),
|
|
65
76
|
...(speech === undefined ? [] : [speechLine(speech)]),
|
|
66
77
|
...(fromBefore === true ? [fromBeforeLine] : []),
|
|
67
|
-
...(problem !== undefined ? [problem] : gameLines(game, words, analysis?.brought === true)),
|
|
78
|
+
...(problem !== undefined ? [problem] : gameLines(game, words, analysis?.brought === true, pageClosed === true, coach === true)),
|
|
68
79
|
...(analysis === undefined ? [] : [analysisLine(analysis)]),
|
|
69
80
|
].join("\n"),
|
|
70
81
|
});
|
|
82
|
+
/** An older init's files in the player's folder: the player runs init again, with the chat closed, since the host reads them as a chat starts. */
|
|
83
|
+
function outdatedLine(files) {
|
|
84
|
+
return `This folder was set up by an older Chesspal (${files.join(", ")}): tell the player, in their language, to close this chat, run "chesspal init" `
|
|
85
|
+
+ "in this folder and open a new chat. Until then the agents and your instructions are the old ones.";
|
|
86
|
+
}
|
|
71
87
|
// The game going on as a chat starts: the player may have come back for it, or want another.
|
|
72
88
|
const fromBeforeLine = "A game from before this chat is going on: ask the player whether to go on with it. For a new one, " + newGameStep;
|
|
73
89
|
/**
|
|
@@ -87,17 +103,26 @@ function fromBeforeChat(context, started) {
|
|
|
87
103
|
const start = lastChatStart(context.folder);
|
|
88
104
|
return start === undefined || cleanSince(start, started);
|
|
89
105
|
}
|
|
90
|
-
/** The game in analysis; the next step when the player has just brought it on the board page
|
|
91
|
-
function analysisLine({ game, brought }) {
|
|
92
|
-
|
|
93
|
-
|
|
106
|
+
/** The game in analysis; the next step when the player has just brought it on the board page. */
|
|
107
|
+
function analysisLine({ game, brought, analyst }) {
|
|
108
|
+
if (brought === true) {
|
|
109
|
+
return analyst === true
|
|
110
|
+
? `The player brought ${game} on the board page to analyse it. Next: ${analystLine(game)}`
|
|
111
|
+
: `The player brought ${game} on the board page to analyse it. Next: call analyse_game {"game": "${game}"}, then keep your review on that page with annotate_game, and go over it with them.`;
|
|
112
|
+
}
|
|
113
|
+
return analyst === true
|
|
114
|
+
? `In analysis on the board page: ${game}. ${reviewedLine(game)}`
|
|
94
115
|
: `In analysis on the board page: ${game}; analyse_game {"game": "${game}"} goes over it with the player.`;
|
|
95
116
|
}
|
|
96
|
-
/**
|
|
97
|
-
|
|
117
|
+
/**
|
|
118
|
+
* The game's lines; a game the player brought to analyse takes the place of the next step. The coach to start goes just before the next step, where
|
|
119
|
+
* the AI acts on it (Priya).
|
|
120
|
+
*/
|
|
121
|
+
function gameLines(game, words, brought, pageClosed, coach) {
|
|
122
|
+
const closing = [...(coach ? [agentsLine([coachAgent])] : []), ...(brought ? wordLines(words) : closingLines(game, words, pageClosed))];
|
|
98
123
|
if (game === undefined) {
|
|
99
|
-
return ["No game.", ...
|
|
124
|
+
return ["No game.", ...closing];
|
|
100
125
|
}
|
|
101
126
|
const moves = game.lastMoves === "" ? [] : [`Moves: ${game.lastMoves}`];
|
|
102
|
-
return [`Game: ${sidesLine(game.ai)}, ${levelText(game.level)}.`, ...moves, ...positionLines(game), ...
|
|
127
|
+
return [`Game: ${sidesLine(game.ai)}, ${levelText(game.level)}.`, ...moves, ...positionLines(game), ...closing];
|
|
103
128
|
}
|
|
@@ -14,7 +14,7 @@ export const studyGames = defineCommand({
|
|
|
14
14
|
input: z.object({}),
|
|
15
15
|
readOnly: true,
|
|
16
16
|
idempotent: true,
|
|
17
|
-
run: (
|
|
17
|
+
run: (input, context) => {
|
|
18
18
|
const folder = gameFolder(context.home());
|
|
19
19
|
return { games: keptGames(folder).flatMap((name) => studyLines(folder, name)) };
|
|
20
20
|
},
|
package/dist/commands/study.js
CHANGED
|
@@ -2,7 +2,7 @@
|
|
|
2
2
|
// goes on, nothing is studied: the analysis would help the game being played (D-60, D-62).
|
|
3
3
|
import { z } from "zod";
|
|
4
4
|
import { Game } from "../core/index.js";
|
|
5
|
-
import { archivedGame, archivedGames, archivedName, endOf, keptGame,
|
|
5
|
+
import { archivedGame, archivedGames, archivedName, endOf, keptGame, listedName } from "../games/index.js";
|
|
6
6
|
import { gameFolder } from "../profiles/index.js";
|
|
7
7
|
import { gameAt } from "./clock.js";
|
|
8
8
|
import { colourName } from "./view.js";
|
|
@@ -41,7 +41,7 @@ export function gameToStudy(context, name) {
|
|
|
41
41
|
/** A game played or kept to study by its name as the lists write it, or without its folder or its .pgn; refused when it is not there. */
|
|
42
42
|
export function namedGame(context, name) {
|
|
43
43
|
const folder = gameFolder(context.home());
|
|
44
|
-
const full =
|
|
44
|
+
const full = listedName(folder, name);
|
|
45
45
|
return { record: full.startsWith("study/") ? keptGame(folder, full) : archivedGame(folder, full), name: full };
|
|
46
46
|
}
|
|
47
47
|
/** The index of a move in the game's record, given as analyse_game numbers it: 12. for White's, 12... for Black's, 12...Kf8 too. */
|
|
@@ -52,7 +52,7 @@ export function moveIndex(record, move) {
|
|
|
52
52
|
export function moveNumbers(record) {
|
|
53
53
|
const start = new Game({ tags: record.tags, moves: [] }).position;
|
|
54
54
|
const blackFirst = start.turn === "black" ? 1 : 0;
|
|
55
|
-
return record.moves.map((
|
|
55
|
+
return record.moves.map((move, index) => {
|
|
56
56
|
const ply = index + blackFirst;
|
|
57
57
|
return `${start.moveNumber + Math.floor(ply / 2)}${ply % 2 === 0 ? "." : "..."}`;
|
|
58
58
|
});
|
|
@@ -79,22 +79,6 @@ export function positionLine({ game, move }, name) {
|
|
|
79
79
|
const { outcome, position } = game;
|
|
80
80
|
return `${where}: ${outcome.over ? `the board ends the game by ${outcome.ending}` : `${colourName(position.turn)} to move`}.`;
|
|
81
81
|
}
|
|
82
|
-
/**
|
|
83
|
-
* A game's name as the lists write it, from a name without its folder or its .pgn too: 2026-11-04-173054 is games/2026-11-04-173054.pgn, or the game kept
|
|
84
|
-
* to study by that name when no game played has it; any other name as it is, for the archive to refuse.
|
|
85
|
-
*/
|
|
86
|
-
function fullName(folder, name) {
|
|
87
|
-
const [, shelf, stem] = /^\s*(?:(games|study)\/)?(\d{4}-\d{2}-\d{2}-\d{6})(?:\.pgn)?\s*$/.exec(name) ?? [];
|
|
88
|
-
if (stem === undefined) {
|
|
89
|
-
return name;
|
|
90
|
-
}
|
|
91
|
-
if (shelf !== undefined) {
|
|
92
|
-
return `${shelf}/${stem}.pgn`;
|
|
93
|
-
}
|
|
94
|
-
const played = `games/${stem}.pgn`;
|
|
95
|
-
const kept = `study/${stem}.pgn`;
|
|
96
|
-
return !archivedGames(folder).includes(played) && keptGames(folder).includes(kept) ? kept : played;
|
|
97
|
-
}
|
|
98
82
|
function plyOf(record, numbers, move) {
|
|
99
83
|
const [, number, dots, san] = movePattern.exec(move) ?? [];
|
|
100
84
|
if (number === undefined) {
|
package/dist/core/facts.js
CHANGED
|
@@ -23,6 +23,21 @@ const order = { k: 0, q: 1, r: 2, b: 3, n: 4, p: 5 };
|
|
|
23
23
|
// The lines from a square: a step on the file and the rank, and the slider that moves along it besides the queen.
|
|
24
24
|
const lines = [[0, 1, "r"], [0, -1, "r"], [1, 0, "r"], [-1, 0, "r"], [1, 1, "b"], [1, -1, "b"], [-1, 1, "b"], [-1, -1, "b"]];
|
|
25
25
|
const files = "abcdefgh";
|
|
26
|
+
/** Which pieces attack a square as the facts count them: a piece pinned to its king only along the pin's line, though it still gives check; no en passant. */
|
|
27
|
+
export function attacksOf(chess) {
|
|
28
|
+
return alongPins(chess, piecesOf(chess).filter((piece) => piece.type === "k").flatMap((king) => pinsTo(chess, king)));
|
|
29
|
+
}
|
|
30
|
+
/** The squares strictly between two squares on one line. */
|
|
31
|
+
export function squaresBetween(from, to) {
|
|
32
|
+
const ray = rayFrom(from, Math.sign(fileOf(to) - fileOf(from)), Math.sign(rankOf(to) - rankOf(from)));
|
|
33
|
+
return ray.slice(0, ray.indexOf(to));
|
|
34
|
+
}
|
|
35
|
+
export function fileOf(square) {
|
|
36
|
+
return files.indexOf(square[0]);
|
|
37
|
+
}
|
|
38
|
+
export function rankOf(square) {
|
|
39
|
+
return Number(square[1]);
|
|
40
|
+
}
|
|
26
41
|
function computed(chess, legal) {
|
|
27
42
|
const placed = piecesOf(chess);
|
|
28
43
|
const turn = chess.turn();
|
|
@@ -49,10 +64,6 @@ function computed(chess, legal) {
|
|
|
49
64
|
};
|
|
50
65
|
return chess.inCheck() ? facts : { ...facts, otherChecks: otherChecks(chess) };
|
|
51
66
|
}
|
|
52
|
-
/** Which pieces attack a square as the facts count them: a piece pinned to its king only along the pin's line, though it still gives check; no en passant. */
|
|
53
|
-
export function attacksOf(chess) {
|
|
54
|
-
return alongPins(chess, piecesOf(chess).filter((piece) => piece.type === "k").flatMap((king) => pinsTo(chess, king)));
|
|
55
|
-
}
|
|
56
67
|
function reachOf(chess, kingPins, legal) {
|
|
57
68
|
const direct = alongPins(chess, kingPins);
|
|
58
69
|
const enPassant = enPassantVictim(chess);
|
|
@@ -148,17 +159,6 @@ function rayFrom(from, fileStep, rankStep) {
|
|
|
148
159
|
}
|
|
149
160
|
return ray;
|
|
150
161
|
}
|
|
151
|
-
/** The squares strictly between two squares on one line. */
|
|
152
|
-
export function squaresBetween(from, to) {
|
|
153
|
-
const ray = rayFrom(from, Math.sign(fileOf(to) - fileOf(from)), Math.sign(rankOf(to) - rankOf(from)));
|
|
154
|
-
return ray.slice(0, ray.indexOf(to));
|
|
155
|
-
}
|
|
156
|
-
export function fileOf(square) {
|
|
157
|
-
return files.indexOf(square[0]);
|
|
158
|
-
}
|
|
159
|
-
export function rankOf(square) {
|
|
160
|
-
return Number(square[1]);
|
|
161
|
-
}
|
|
162
162
|
/** Compares two names of squares or colours: a fixed alphabet, no locale. */
|
|
163
163
|
function compare(left, right) {
|
|
164
164
|
return left < right ? -1 : left > right ? 1 : 0;
|
package/dist/core/game.d.ts
CHANGED
|
@@ -73,7 +73,7 @@ export declare class Game {
|
|
|
73
73
|
get lastMove(): Move | undefined;
|
|
74
74
|
/** What the position shows (D-26): attackers and defenders, pieces at risk, pins, checks, the moves of each piece; computed once for each position. */
|
|
75
75
|
get facts(): Facts;
|
|
76
|
-
/** The positional profile (D-19
|
|
76
|
+
/** The positional profile (D-19): pawns, files, outposts, space, mobility, development, king safety, control, phase, draws; computed once for each position. */
|
|
77
77
|
get profile(): Profile;
|
|
78
78
|
/** The legal moves, or those of the piece on a square. */
|
|
79
79
|
legalMoves(square?: Square): readonly Move[];
|
|
@@ -91,3 +91,5 @@ export declare class Game {
|
|
|
91
91
|
private illegal;
|
|
92
92
|
private snapshot;
|
|
93
93
|
}
|
|
94
|
+
/** A text with SAN's letters and signs for the figurines and signs others write: ♘f3 as Nf3, × as x; a pawn's figurine says nothing. */
|
|
95
|
+
export declare function withSanLetters(text: string): string;
|
package/dist/core/game.js
CHANGED
|
@@ -65,7 +65,7 @@ export class Game {
|
|
|
65
65
|
get facts() {
|
|
66
66
|
return factsOf(this.chess, legalMovesOf(this.chess));
|
|
67
67
|
}
|
|
68
|
-
/** The positional profile (D-19
|
|
68
|
+
/** The positional profile (D-19): pawns, files, outposts, space, mobility, development, king safety, control, phase, draws; computed once for each position. */
|
|
69
69
|
get profile() {
|
|
70
70
|
const key = this.chess.hash();
|
|
71
71
|
return profileOf(this.chess, { repetitions: this.keys.filter((seen) => seen === key).length, castled: this.castled, fromFen: this.tags.FEN !== undefined }, legalMovesOf(this.chess));
|
|
@@ -150,7 +150,7 @@ export class Game {
|
|
|
150
150
|
}
|
|
151
151
|
const [, piece, file, rank, separator, target = "", promotion] = parts;
|
|
152
152
|
const capture = separator === "x" || separator === ":";
|
|
153
|
-
// "bc4" is a bishop without its capital, or a pawn's capture without its x, as "bb4" or "cc6" is a piece or a pawn: never guessed (
|
|
153
|
+
// "bc4" is a bishop without its capital, or a pawn's capture without its x, as "bb4" or "cc6" is a piece or a pawn: never guessed (Anatolij, round of D-87).
|
|
154
154
|
if (piece === undefined && file !== undefined && rank === undefined && !capture) {
|
|
155
155
|
return smallLetter(input, file, target);
|
|
156
156
|
}
|
|
@@ -210,6 +210,10 @@ const asciiOf = {
|
|
|
210
210
|
"♙": "",
|
|
211
211
|
"♟": "",
|
|
212
212
|
};
|
|
213
|
+
/** A text with SAN's letters and signs for the figurines and signs others write: ♘f3 as Nf3, × as x; a pawn's figurine says nothing. */
|
|
214
|
+
export function withSanLetters(text) {
|
|
215
|
+
return text.replace(/[︎️]/g, "").replace(/[–—−×♔-♟]/g, (sign) => asciiOf[sign] ?? sign);
|
|
216
|
+
}
|
|
213
217
|
// The pieces' letters of other languages that name one piece only: the Italian, French, Spanish and German ones; R is the rook in SAN.
|
|
214
218
|
const foreignPieces = {
|
|
215
219
|
C: ["knight", "N"],
|
|
@@ -260,7 +264,7 @@ function normalized(text) {
|
|
|
260
264
|
return text.trim()
|
|
261
265
|
.replace(/^\d+\s*(?:\.[\s.]*|…\s*)/, "")
|
|
262
266
|
.replace(/[︎️]/g, "")
|
|
263
|
-
// A space after the piece's letter, "N f3", as an AI may show the player how to write (Priya
|
|
267
|
+
// A space after the piece's letter, "N f3", as an AI may show the player how to write (Priya).
|
|
264
268
|
.replace(/^([A-Z♔-♟])\s+(?=[a-h1-8x:])/, "$1")
|
|
265
269
|
.replace(/[–—−×♔-♟]/g, (sign) => asciiOf[sign] ?? sign)
|
|
266
270
|
// A small t too, so that "tf1" is told the rook's R as "Tf1" is.
|
|
@@ -298,7 +302,7 @@ function kingInCheckOffTurn(chess) {
|
|
|
298
302
|
function gameOver({ ending, result }) {
|
|
299
303
|
return { refusal: "over", message: `The game is over by ${ending} (${result}): no move can follow.` };
|
|
300
304
|
}
|
|
301
|
-
/** A move written with a piece's letter of another language
|
|
305
|
+
/** A move written with a piece's letter of another language: Cf3 for an Italian or French knight, Dd1 for a queen; none for another mistake. */
|
|
302
306
|
function foreignLetter(input, bare) {
|
|
303
307
|
const [, move = "", becomes = ""] = /^(.*[18])=?([A-Z])$/.exec(bare) ?? [];
|
|
304
308
|
if (becomes !== "" && !"QRBN".includes(becomes)) {
|
package/dist/core/illegal.js
CHANGED
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
// Why the board refuses a move, without judging anything (D-18): the page tells the player who tried it
|
|
1
|
+
// Why the board refuses a move, without judging anything (D-18): the page tells the player who tried it.
|
|
2
2
|
import { Chess } from "chess.js";
|
|
3
3
|
import { fileOf, rankOf, squaresBetween } from "./facts.js";
|
|
4
4
|
/** Why the piece of the side to move on one square cannot go to another, which its legal moves do not reach; undefined when no rule says why. */
|
package/dist/core/index.d.ts
CHANGED
|
@@ -2,18 +2,19 @@ export { boardText, figurinesOf } from "./board-text.ts";
|
|
|
2
2
|
export { canMate, clockAfterMove, clockOfComment, clockStarted, clockTag, clockText, startClock, timeControlOf, timeControlOfTag, timeControlTag, timeControlText, timeLeft } from "./clock.ts";
|
|
3
3
|
export type { Clock, TimeControl } from "./clock.ts";
|
|
4
4
|
export type { Facts, PieceFacts, PieceLetter, Pin } from "./facts.ts";
|
|
5
|
-
export { Game } from "./game.ts";
|
|
5
|
+
export { Game, withSanLetters } from "./game.ts";
|
|
6
6
|
export type { Ending, Move, Outcome, Played, Position, Promotion, Refusal, Side, Square } from "./game.ts";
|
|
7
7
|
export type { Illegal, IllegalReason } from "./illegal.ts";
|
|
8
|
+
export { type Lead, leadOf, leadText, readLead, withLead } from "./lead.ts";
|
|
8
9
|
export { aiLevels, layersOf, levelForPlayer, levelOf, levelTag, sees, suggestedLevel } from "./levels.ts";
|
|
9
10
|
export type { AiLevel, Layer } from "./levels.ts";
|
|
10
11
|
export { materialOf } from "./material.ts";
|
|
11
12
|
export type { Material } from "./material.ts";
|
|
12
|
-
export { endWithMood, type Mood, moodAt,
|
|
13
|
-
export {
|
|
13
|
+
export { endWithMood, type Mood, moodAt, type MoodNow, moodOf, moods, moodTag, withoutMoods } from "./moods.ts";
|
|
14
|
+
export { bookMoves, indexBook, indexOpenings, inOpenings, openingOf, outOfBookMove } from "./openings.ts";
|
|
14
15
|
export type { Opening, OpeningBook, OpeningIndex } from "./openings.ts";
|
|
15
16
|
export { pgnDate, readPgn, writePgn } from "./pgn.ts";
|
|
16
17
|
export type { BishopFacts, CentreSquare, KingFacts, Outpost, PawnFacts, PawnSquare, Phase, Profile, SideProfile } from "./profile.ts";
|
|
17
18
|
export { movesOnly } from "./record.ts";
|
|
18
19
|
export type { Annotation, GameRecord, RecordedMove } from "./record.ts";
|
|
19
|
-
export { type AiModel, aiModelIn, annotatorOf, arrowOf, type Badge, badges, closingOf, type DrawColour, drawingsIn, drawingsText, type DrawnArrow, type DrawnSquare, gameReviewOf,
|
|
20
|
+
export { type AiModel, aiModelIn, annotatorOf, arrowOf, type Badge, badges, closingOf, type DrawColour, drawingsIn, drawingsText, type DrawnArrow, type DrawnSquare, gameReviewOf, isReviewed, type MoveReview, reviewed, reviewOf, squareOf, unreviewed, withAiModel, withAnnotator, withGameReview, } from "./review.ts";
|
package/dist/core/index.js
CHANGED
|
@@ -1,11 +1,12 @@
|
|
|
1
1
|
// The chess core: the game and its rules, the facts of a position, its record, PGN, the openings. It runs in the browser too (D-17, D-18).
|
|
2
2
|
export { boardText, figurinesOf } from "./board-text.js";
|
|
3
3
|
export { canMate, clockAfterMove, clockOfComment, clockStarted, clockTag, clockText, startClock, timeControlOf, timeControlOfTag, timeControlTag, timeControlText, timeLeft } from "./clock.js";
|
|
4
|
-
export { Game } from "./game.js";
|
|
4
|
+
export { Game, withSanLetters } from "./game.js";
|
|
5
|
+
export { leadOf, leadText, readLead, withLead } from "./lead.js";
|
|
5
6
|
export { aiLevels, layersOf, levelForPlayer, levelOf, levelTag, sees, suggestedLevel } from "./levels.js";
|
|
6
7
|
export { materialOf } from "./material.js";
|
|
7
|
-
export { endWithMood, moodAt,
|
|
8
|
-
export {
|
|
8
|
+
export { endWithMood, moodAt, moodOf, moods, moodTag, withoutMoods } from "./moods.js";
|
|
9
|
+
export { bookMoves, indexBook, indexOpenings, inOpenings, openingOf, outOfBookMove } from "./openings.js";
|
|
9
10
|
export { pgnDate, readPgn, writePgn } from "./pgn.js";
|
|
10
11
|
export { movesOnly } from "./record.js";
|
|
11
|
-
export { aiModelIn, annotatorOf, arrowOf, badges, closingOf, drawingsIn, drawingsText, gameReviewOf,
|
|
12
|
+
export { aiModelIn, annotatorOf, arrowOf, badges, closingOf, drawingsIn, drawingsText, gameReviewOf, isReviewed, reviewed, reviewOf, squareOf, unreviewed, withAiModel, withAnnotator, withGameReview, } from "./review.js";
|
|
@@ -0,0 +1,15 @@
|
|
|
1
|
+
import { type RecordedMove } from "./record.ts";
|
|
2
|
+
/** Who is ahead after a move: pawns from White's side (+1.5 White, -3 Black), or a mate in so many moves (#3 White's, #-3 Black's). */
|
|
3
|
+
export type Lead = {
|
|
4
|
+
readonly pawns: number;
|
|
5
|
+
} | {
|
|
6
|
+
readonly mate: number;
|
|
7
|
+
};
|
|
8
|
+
/** A lead as the AI writes it: +1.5, -3, 0, #3, #-2; none when it is not one. */
|
|
9
|
+
export declare function readLead(text: string): Lead | undefined;
|
|
10
|
+
/** A lead as the PGN and the page write it: +1.5, -3, 0, #3, #-2. */
|
|
11
|
+
export declare function leadText(lead: Lead): string;
|
|
12
|
+
/** The lead a move's comment carries, when the AI estimated one. */
|
|
13
|
+
export declare function leadOf(comment: string | undefined): Lead | undefined;
|
|
14
|
+
/** The move with the AI's lead in place of the one it had, beside what its comment held. */
|
|
15
|
+
export declare function withLead(move: RecordedMove, lead: Lead): RecordedMove;
|
|
@@ -0,0 +1,40 @@
|
|
|
1
|
+
// Who is ahead in a position, as the AI estimates it (D-90): in pawns from White's side, as chess.com shows it, or a mate it sees. It rides in a move's
|
|
2
|
+
// comment as [%lead +1.5] or [%lead #-3], Chesspal's own command and not [%eval], which elsewhere would pass for an engine's. Chesspal keeps it and draws
|
|
3
|
+
// it, never computes it (D-6, D-19).
|
|
4
|
+
import { recordedMove } from "./record.js";
|
|
5
|
+
/** A lead as the AI writes it: +1.5, -3, 0, #3, #-2; none when it is not one. */
|
|
6
|
+
export function readLead(text) {
|
|
7
|
+
const plain = text.trim().replaceAll("−", "-").replace(/^M/i, "#").replace(/^([+-])[#M]/i, "#$1");
|
|
8
|
+
const mate = /^#([+-]?)(\d+)$/.exec(plain);
|
|
9
|
+
if (mate !== null) {
|
|
10
|
+
const moves = Number(mate[2]);
|
|
11
|
+
return moves < 1 || moves > leadLimit ? undefined : { mate: mate[1] === "-" ? -moves : moves };
|
|
12
|
+
}
|
|
13
|
+
if (!/^[+-]?\d+(\.\d+)?$/.test(plain)) {
|
|
14
|
+
return undefined;
|
|
15
|
+
}
|
|
16
|
+
// To a tenth, a half away from zero on both sides; never a negative zero: -0.04 is an even game.
|
|
17
|
+
const figure = Number(plain);
|
|
18
|
+
const pawns = Math.sign(figure) * Math.round(Math.abs(figure) * 10) / 10;
|
|
19
|
+
return Math.abs(pawns) > leadLimit ? undefined : { pawns: pawns === 0 ? 0 : pawns };
|
|
20
|
+
}
|
|
21
|
+
/** A lead as the PGN and the page write it: +1.5, -3, 0, #3, #-2. */
|
|
22
|
+
export function leadText(lead) {
|
|
23
|
+
if ("mate" in lead) {
|
|
24
|
+
return `#${lead.mate}`;
|
|
25
|
+
}
|
|
26
|
+
return lead.pawns > 0 ? `+${lead.pawns}` : `${lead.pawns}`;
|
|
27
|
+
}
|
|
28
|
+
/** The lead a move's comment carries, when the AI estimated one. */
|
|
29
|
+
export function leadOf(comment) {
|
|
30
|
+
const found = leadPattern.exec(comment ?? "")?.[1];
|
|
31
|
+
return found === undefined ? undefined : readLead(found);
|
|
32
|
+
}
|
|
33
|
+
/** The move with the AI's lead in place of the one it had, beside what its comment held. */
|
|
34
|
+
export function withLead(move, lead) {
|
|
35
|
+
const comment = [(move.comment ?? "").replace(/\s*\[%lead [^\]]*\]/g, "").trim(), `[%lead ${leadText(lead)}]`].filter((part) => part !== "").join(" ");
|
|
36
|
+
return recordedMove(move.san, move.nags, comment);
|
|
37
|
+
}
|
|
38
|
+
const leadPattern = /\[%lead ([^\]]*)\]/;
|
|
39
|
+
// The largest lead Chesspal keeps, in pawns or moves to mate: beyond it the AI's figure says nothing more.
|
|
40
|
+
const leadLimit = 99;
|
package/dist/core/levels.d.ts
CHANGED
|
@@ -2,7 +2,7 @@ import type { GameRecord } from "./record.ts";
|
|
|
2
2
|
/** The AI's levels, the weakest first. */
|
|
3
3
|
export declare const aiLevels: readonly ["beginner", "club", "strong", "master"];
|
|
4
4
|
export type AiLevel = (typeof aiLevels)[number];
|
|
5
|
-
/** The layers of facts: the board as the player sees it (D-59), the tactical view (D-26), the positional profile
|
|
5
|
+
/** The layers of facts: the board as the player sees it (D-59), the tactical view (D-26), the positional profile, the opening book's moves (D-15). */
|
|
6
6
|
declare const layers: readonly ["board", "tactics", "strategy", "theory"];
|
|
7
7
|
export type Layer = (typeof layers)[number];
|
|
8
8
|
/** The PGN tag that keeps a game's level, so the archive keeps it too. */
|
package/dist/core/levels.js
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
/** The AI's levels, the weakest first. */
|
|
2
2
|
export const aiLevels = ["beginner", "club", "strong", "master"];
|
|
3
|
-
/** The layers of facts: the board as the player sees it (D-59), the tactical view (D-26), the positional profile
|
|
3
|
+
/** The layers of facts: the board as the player sees it (D-59), the tactical view (D-26), the positional profile, the opening book's moves (D-15). */
|
|
4
4
|
const layers = ["board", "tactics", "strategy", "theory"];
|
|
5
5
|
/** The PGN tag that keeps a game's level, so the archive keeps it too. */
|
|
6
6
|
export const levelTag = "AILevel";
|
package/dist/core/moods.d.ts
CHANGED
|
@@ -4,8 +4,6 @@ import type { GameRecord } from "./record.ts";
|
|
|
4
4
|
export declare const moods: readonly ["neutral", "happy", "surprised", "worried", "thoughtful", "sad"];
|
|
5
5
|
/** A mood of the AI. */
|
|
6
6
|
export type Mood = (typeof moods)[number];
|
|
7
|
-
/** How many of the AI's moves each mood lasts, the one it comes with included: a surprise is a flash (Julián, round of T-107). */
|
|
8
|
-
export declare const moodMoves: Readonly<Record<Mood, number>>;
|
|
9
7
|
/** The AI's mood at a point of a game, and how many more of its moves keep it before it fades: 0 when its next move ends it. */
|
|
10
8
|
export interface MoodNow {
|
|
11
9
|
readonly mood: Mood;
|
package/dist/core/moods.js
CHANGED
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
/** The moods of the AI, which the Torretta shows. */
|
|
2
2
|
export const moods = ["neutral", "happy", "surprised", "worried", "thoughtful", "sad"];
|
|
3
|
-
/** How many of the AI's moves each mood lasts, the one it comes with included: a surprise is a flash (Julián
|
|
4
|
-
|
|
3
|
+
/** How many of the AI's moves each mood lasts, the one it comes with included: a surprise is a flash (Julián). */
|
|
4
|
+
const moodMoves = { neutral: 0, happy: 3, surprised: 1, worried: 3, thoughtful: 3, sad: 3 };
|
|
5
5
|
/** The mood as a move's comment carries it. */
|
|
6
6
|
export function moodTag(mood) {
|
|
7
7
|
return `[%mood ${mood}]`;
|
package/dist/core/openings.d.ts
CHANGED
|
@@ -15,8 +15,6 @@ export interface Opening {
|
|
|
15
15
|
/** Whether the game's position now is a named one; when not, it left the book at the ply after `ply`. */
|
|
16
16
|
readonly inBook: boolean;
|
|
17
17
|
}
|
|
18
|
-
/** No line of the book is longer: past it, no position is looked up. */
|
|
19
|
-
export declare const bookDepth = 40;
|
|
20
18
|
/** The book's moves: each position on a line of Lichess's files to the moves its lines play from it, the theory the AI knows at the master level (D-15, D-60). */
|
|
21
19
|
export type OpeningBook = Readonly<Record<string, readonly string[]>>;
|
|
22
20
|
/** The index of the openings in Lichess's TSV files (eco, name, pgn), each line keyed by the position its moves reach. */
|
package/dist/core/openings.js
CHANGED
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
// The openings by position (D-15, D-16): Lichess's names, indexed by the position each line reaches, so transpositions find them too.
|
|
2
2
|
import { Chess } from "chess.js";
|
|
3
3
|
/** No line of the book is longer: past it, no position is looked up. */
|
|
4
|
-
|
|
4
|
+
const bookDepth = 40;
|
|
5
5
|
/** The index of the openings in Lichess's TSV files (eco, name, pgn), each line keyed by the position its moves reach. */
|
|
6
6
|
export function indexOpenings(tsv) {
|
|
7
7
|
const index = {};
|
package/dist/core/profile.js
CHANGED
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
// The positional profile (D-19
|
|
1
|
+
// The positional profile (D-19): pawns, files, bishops, outposts, space and centre, mobility, development, king safety, control, phase, draws and
|
|
2
2
|
// the geometry of pawn endings, each a separate fact; never weighed, never summed.
|
|
3
3
|
import { Chess } from "chess.js";
|
|
4
4
|
import { attacksOf, fileOf, rankOf } from "./facts.js";
|
package/dist/core/record.d.ts
CHANGED
|
@@ -13,7 +13,7 @@ export interface GameRecord {
|
|
|
13
13
|
readonly comment?: string;
|
|
14
14
|
readonly moves: readonly RecordedMove[];
|
|
15
15
|
}
|
|
16
|
-
/** The game with its tags and moves alone, without comments, plans or judgments: for Lichess or chess.com to load
|
|
16
|
+
/** The game with its tags and moves alone, without comments, plans or judgments: for Lichess or chess.com to load. */
|
|
17
17
|
export declare function movesOnly(record: GameRecord): GameRecord;
|
|
18
18
|
/** A recorded move, frozen, with only the annotations it has. */
|
|
19
19
|
export declare function recordedMove(san: string, nags?: readonly number[], comment?: string): RecordedMove;
|
package/dist/core/record.js
CHANGED
|
@@ -1,5 +1,5 @@
|
|
|
1
1
|
// A game as plain data: the form it takes on disk (D-27) and in a PGN.
|
|
2
|
-
/** The game with its tags and moves alone, without comments, plans or judgments: for Lichess or chess.com to load
|
|
2
|
+
/** The game with its tags and moves alone, without comments, plans or judgments: for Lichess or chess.com to load. */
|
|
3
3
|
export function movesOnly(record) {
|
|
4
4
|
return { tags: record.tags, moves: record.moves.map((move) => ({ san: move.san })) };
|
|
5
5
|
}
|
package/dist/core/review.d.ts
CHANGED
|
@@ -4,7 +4,7 @@ export declare const badges: readonly ["brilliant", "great", "best", "excellent"
|
|
|
4
4
|
/** A move's badge. */
|
|
5
5
|
export type Badge = (typeof badges)[number];
|
|
6
6
|
/** The colours the AI draws with on the board, by the letters PGN's [%cal] and [%csl] write them with. */
|
|
7
|
-
|
|
7
|
+
declare const drawColours: {
|
|
8
8
|
readonly G: "green";
|
|
9
9
|
readonly R: "red";
|
|
10
10
|
readonly Y: "yellow";
|
|
@@ -42,8 +42,15 @@ export declare function squareOf(text: string): DrawnSquare | undefined;
|
|
|
42
42
|
export declare function gameReviewOf(record: GameRecord): string | undefined;
|
|
43
43
|
/** The AI's last word on how the game ended, when it wrote one. */
|
|
44
44
|
export declare function closingOf(record: GameRecord): string | undefined;
|
|
45
|
+
/** Whether the analyst has reviewed a game: its word on the whole game or on how it ended. The badges given during the game with the helps on are not a review (D-78). */
|
|
46
|
+
export declare function isReviewed(record: GameRecord): boolean;
|
|
45
47
|
/** The move with the AI's review in place of the one it had: the NAG of its badge, and its badge and note in the comment, beside what the comment held. */
|
|
46
48
|
export declare function reviewed(move: RecordedMove, review: MoveReview): RecordedMove;
|
|
49
|
+
/**
|
|
50
|
+
* The record without the AI's review (D-92): the badges with the NAGs they wrote, the notes, drawings and estimates of who is ahead on the moves, the word on
|
|
51
|
+
* the game and who signed it. What the comments held besides stays, as do the NAGs of moves without a badge and the Annotator of a game it never reviewed.
|
|
52
|
+
*/
|
|
53
|
+
export declare function unreviewed(record: GameRecord): GameRecord;
|
|
47
54
|
/** The arrows and squares as PGN's [%cal] and [%csl] write them, for a comment; empty without any. */
|
|
48
55
|
export declare function drawingsText({ arrows, squares }: Pick<MoveReview, "arrows" | "squares">): string;
|
|
49
56
|
/** The record with who reviewed it (D-81): the model, else the host, as PGN's Annotator, and the effort only when known; an effort no longer known goes. */
|
|
@@ -70,5 +77,4 @@ export declare function withGameReview(record: GameRecord, { summary, closing }:
|
|
|
70
77
|
summary?: string;
|
|
71
78
|
closing?: string;
|
|
72
79
|
}): GameRecord;
|
|
73
|
-
|
|
74
|
-
export declare function isBadge(word: string | undefined): word is Badge;
|
|
80
|
+
export {};
|