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,34 +1,25 @@
|
|
|
1
|
-
import { jsx as _jsx,
|
|
1
|
+
import { jsx as _jsx, jsxs as _jsxs, Fragment as _Fragment } from "preact/jsx-runtime";
|
|
2
2
|
// The talk on the board page (D-51, D-53): the AI's words in bubbles that point at the Torretta, the player's above the box they write in.
|
|
3
3
|
import { createContext } from "preact";
|
|
4
4
|
import { useContext, useEffect, useLayoutEffect, useRef } from "preact/hooks";
|
|
5
|
-
import {
|
|
6
|
-
import {
|
|
7
|
-
import { Figurines } from "
|
|
8
|
-
import { talkLimits } from "
|
|
9
|
-
import {
|
|
5
|
+
import { Torretta } from "../avatars/torretta.js";
|
|
6
|
+
import { BadgeIcon, NoteIcon } from "../game/badges.js";
|
|
7
|
+
import { Figurines } from "../game/move-list.js";
|
|
8
|
+
import { talkLimits } from "../game/plies.js";
|
|
9
|
+
import { signature } from "../players/model-name.js";
|
|
10
10
|
import { hush, speak } from "./voice.js";
|
|
11
|
-
/**
|
|
12
|
-
|
|
13
|
-
* on, its judgment of the player's last move comes newest, in a line that opens on its note (D-78).
|
|
14
|
-
*/
|
|
15
|
-
export function AiWords({ words, newestFirst, voice, judged, text }) {
|
|
11
|
+
/** The AI's words of the game, a bubble each, the newest by the Torretta: below it, or above it on a board turned round; the first points at it. */
|
|
12
|
+
export function AiWords({ words, newestFirst, voice }) {
|
|
16
13
|
const list = useRef(null);
|
|
17
14
|
useOnlyWhole(list, words, newestFirst);
|
|
18
15
|
useSpokenNews(words, voice);
|
|
19
|
-
|
|
20
|
-
// The judgment sits by the Torretta, out of the bubbles' order: it never pushes the AI's words away.
|
|
21
|
-
if (judged === undefined) {
|
|
22
|
-
return says;
|
|
23
|
-
}
|
|
24
|
-
const line = _jsx(Judged, { ply: judged, text: text });
|
|
25
|
-
return newestFirst ? _jsxs(_Fragment, { children: [line, says] }) : _jsxs(_Fragment, { children: [says, line] });
|
|
16
|
+
return (_jsx("ol", { ref: list, class: "says", "aria-live": "polite", children: inOrder(words.map((word, index) => (_jsx("li", { class: "say", style: aged(words.length - 1 - index), children: _jsx(Marked, { text: word }) }, index))), newestFirst) }));
|
|
26
17
|
}
|
|
27
18
|
/**
|
|
28
19
|
* The AI's word on the move shown of a game in analysis (D-69), in a bubble that points down at the Torretta beside the AI's name: the move, its badge by name,
|
|
29
20
|
* and its note when it wrote one; read out as the player steps through the game. The Torretta and the name stay when the move has no word.
|
|
30
21
|
*/
|
|
31
|
-
export function AiNote({ ply, opening, closing, summary, name, by, mood, voice, text }) {
|
|
22
|
+
export function AiNote({ ply, opening, closing, summary, reviewing, name, by, mood, voice, text }) {
|
|
32
23
|
// On a move of the book without the AI's note, the AI reports what the book says: the opening in the title, the variation under it.
|
|
33
24
|
const book = ply?.review?.note === undefined ? opening : undefined;
|
|
34
25
|
const shown = ply?.review ?? (book === undefined ? undefined : { badge: "book" });
|
|
@@ -42,13 +33,9 @@ export function AiNote({ ply, opening, closing, summary, name, by, mood, voice,
|
|
|
42
33
|
return hush;
|
|
43
34
|
}, [spoken, voice]);
|
|
44
35
|
// The Torretta stays in sight through the whole analysis, under its bubbles, which show only where it wrote something.
|
|
45
|
-
return (_jsxs("div", { class: "ai-note", "aria-live": "polite", children: [ply === undefined || shown === undefined ? null : (_jsxs("p", { class: `say move-note ${shown.badge ?? ""}`, children: [_jsxs("span", { class: "head", children: [shown.badge === undefined ? _jsx(NoteIcon, {}) : _jsx(BadgeIcon, { badge: shown.badge }), _jsxs("b", { children: [_jsxs("span", { class: "visually-hidden", children: [ply.number, ply.side === "white" ? "." : "...", ply.san] }), _jsxs("span", { "aria-hidden": "true", children: [_jsxs("span", { class: "move-number", children: [ply.number, ply.side === "white" ? "." : "..."] }), _jsx(Figurines, { san: ply.san, side: ply.side })] })] }), " ", title] }), note === undefined ? null : (_jsx("span", { class: "note", children: _jsx(Marked, { text: note }) })), shown.arrows === undefined && shown.squares === undefined ? null : _jsx(Legend, { review: shown,
|
|
46
|
-
}
|
|
47
|
-
|
|
48
|
-
function Judged({ ply, text }) {
|
|
49
|
-
const { badge, note } = ply.review ?? {};
|
|
50
|
-
const head = (_jsxs(_Fragment, { children: [badge === undefined ? _jsx(NoteIcon, {}) : _jsx(BadgeIcon, { badge: badge }), _jsxs("b", { children: [_jsxs("span", { class: "move-number", children: [ply.number, ply.side === "white" ? "." : "..."] }), _jsx(Figurines, { san: ply.san, side: ply.side })] }), " ", badge === undefined ? null : text.badges[badge]] }));
|
|
51
|
-
return (_jsx("div", { class: `say move-note judged ${badge ?? ""}`, children: note === undefined ? _jsx("span", { class: "head", children: head }) : (_jsxs("details", { children: [_jsx("summary", { class: "head", children: head }), _jsx("span", { class: "note", children: _jsx(Marked, { text: note }) })] })) }));
|
|
36
|
+
return (_jsxs("div", { class: "ai-note", "aria-live": "polite", children: [ply === undefined || shown === undefined ? null : (_jsxs("p", { class: `say move-note ${shown.badge ?? ""}`, children: [_jsxs("span", { class: "head", children: [shown.badge === undefined ? _jsx(NoteIcon, {}) : _jsx(BadgeIcon, { badge: shown.badge }), _jsxs("b", { children: [_jsxs("span", { class: "visually-hidden", children: [ply.number, ply.side === "white" ? "." : "...", ply.san] }), _jsxs("span", { "aria-hidden": "true", children: [_jsxs("span", { class: "move-number", children: [ply.number, ply.side === "white" ? "." : "..."] }), _jsx(Figurines, { san: ply.san, side: ply.side })] })] }), " ", title] }), note === undefined ? null : (_jsx("span", { class: "note", children: _jsx(Marked, { text: note }) })), shown.arrows === undefined && shown.squares === undefined ? null : _jsx(Legend, { review: shown, words: text.drawn })] })), summary === undefined ? null : _jsx(GameReview, { by: name, summary: summary, text: text }), closing === undefined ? null : (_jsx("p", { class: "say closing", children: _jsx(Marked, { text: closing }) })), reviewing === true
|
|
37
|
+
? (_jsxs("p", { class: "say reviewing", children: [_jsx("span", { class: "spinner", "aria-hidden": "true" }), text.reviewing(name)] }))
|
|
38
|
+
: null, _jsxs("p", { class: "who", children: [_jsx(Torretta, { size: 36, mood: mood }), _jsxs("span", { class: "signed", children: [name, by === undefined ? null : _jsx("small", { children: signature(by.annotator, by.effort) })] })] })] }));
|
|
52
39
|
}
|
|
53
40
|
/** The squares and moves in the AI's words, such as e3, Cxe4, 7.Nd4 or O-O: in bold, as the player looks for them on the board. */
|
|
54
41
|
export function Marked({ text }) {
|
|
@@ -57,31 +44,18 @@ export function Marked({ text }) {
|
|
|
57
44
|
? (_jsx("b", { children: _jsx(OnBoard, { text: part }) }, index))
|
|
58
45
|
: _jsx(OnBoard, { text: part }, index)) }));
|
|
59
46
|
}
|
|
60
|
-
/** Where the pointer is among the squares and moves in the AI's words
|
|
47
|
+
/** Where the pointer is among the squares and moves in the AI's words: the board lights that square up. */
|
|
61
48
|
export const PointSquare = createContext(() => undefined);
|
|
62
|
-
function OnBoard({ text }) {
|
|
63
|
-
const point = useContext(PointSquare);
|
|
64
|
-
return (_jsx(_Fragment, { children: text.split(boardWords).map((part, index) => index % 2 === 1
|
|
65
|
-
? _jsx("b", { class: "on-board", onPointerEnter: () => point(squareIn(part)), onPointerLeave: (event) => event.pointerType === "mouse" && point(undefined), children: part }, index)
|
|
66
|
-
: part) }));
|
|
67
|
-
}
|
|
68
|
-
/** The square a word names: a square, or where a move goes, the last square in it; none for a castling. */
|
|
69
|
-
function squareIn(word) {
|
|
70
|
-
return /[a-h][1-8](?!.*[a-h][1-8])/.exec(word)?.[0];
|
|
71
|
-
}
|
|
72
49
|
// **a few words** the AI put in bold, as Markdown writes them.
|
|
73
50
|
const boldWords = /\*\*(.+?)\*\*/;
|
|
74
51
|
// A square or a move in SAN or with the pieces' figurines (D-86, D-87), with its number if it has one; the capture group keeps it in split's parts.
|
|
75
52
|
const boardWords = /(?<![\p{L}\d])((?:\d+\.(?:\.\.)?\s?)?(?:O-O(?:-O)?|[KQRBN♔-♟]?[a-h]?[1-8]?x?[a-h][1-8](?:=[QRBN♔-♟])?)[+#]?[!?]{0,2})(?![\p{L}\d])/u;
|
|
76
|
-
/**
|
|
77
|
-
|
|
78
|
-
|
|
79
|
-
|
|
80
|
-
}
|
|
81
|
-
/** What the colours drawn with a note mean, the ones it uses: the AI's legend, for the player (D-69). */
|
|
82
|
-
function Legend({ review, text }) {
|
|
53
|
+
/**
|
|
54
|
+
* What the colours drawn with a note or the coach's hint mean, the ones it uses, in the words of who drew them: the legend, for the player (D-69, Zoe).
|
|
55
|
+
*/
|
|
56
|
+
export function Legend({ review, words }) {
|
|
83
57
|
const used = [...new Set([...(review.arrows ?? []), ...(review.squares ?? [])].map((drawn) => drawn.colour))];
|
|
84
|
-
return (_jsx("span", { class: "legend", children: used.map((colour) => (_jsxs("span", { class: colour, children: [_jsx("i", { "aria-hidden": "true" }),
|
|
58
|
+
return (_jsx("span", { class: "legend", children: used.map((colour) => (_jsxs("span", { class: colour, children: [_jsx("i", { "aria-hidden": "true" }), words[colour]] }, colour))) }));
|
|
85
59
|
}
|
|
86
60
|
/**
|
|
87
61
|
* The player's words of the game, the newest by the box they write in with how far it got, and the box: Enter or the button sends the words alone, the next
|
|
@@ -110,12 +84,31 @@ export function Compose({ lines, newestFirst, spent, draft, onDraft, onSend, can
|
|
|
110
84
|
: _jsx("span", { class: "hint", children: !blank && canMove ? text.withMove : "" }), _jsxs("button", { class: "send", type: "submit", disabled: blank, children: [text.send, _jsx("svg", { class: "icon", viewBox: "0 0 24 24", "aria-hidden": "true", children: _jsx("path", { d: "M5 12H18M13 7L18 12L13 17" }) })] })] })] }))] }));
|
|
111
85
|
}
|
|
112
86
|
/**
|
|
113
|
-
* The talk narrowed to a card beside the board
|
|
87
|
+
* The talk narrowed to a card beside the board: the Torretta above, the player below, each with their name and side written down the card, a ring on
|
|
114
88
|
* whoever moves and a dot on the Torretta when the AI spoke meanwhile.
|
|
115
89
|
*/
|
|
116
90
|
export function TalkFaces({ name, aiPicture, you, picture, ai, player, aiMoves, playerMoves, unread, text }) {
|
|
117
91
|
return (_jsxs("div", { class: "faces", children: [_jsx(RailPlayer, { place: "ai", picture: aiPicture ?? _jsx(Torretta, { size: 40 }), name: name, ...(ai === undefined ? {} : { side: text.sides[ai] }), moves: aiMoves, unread: unread }), _jsx(RailPlayer, { place: "you", picture: picture, name: you, ...(player === undefined ? {} : { side: text.sides[player] }), moves: playerMoves })] }));
|
|
118
92
|
}
|
|
93
|
+
function OnBoard({ text }) {
|
|
94
|
+
const point = useContext(PointSquare);
|
|
95
|
+
return (_jsx(_Fragment, { children: text.split(boardWords).map((part, index) => index % 2 === 1
|
|
96
|
+
? (_jsx("b", { class: "on-board", onPointerEnter: () => point(squareIn(part)), onPointerLeave: (event) => event.pointerType === "mouse" && point(undefined), children: _jsx(Takes, { move: part }) }, index))
|
|
97
|
+
: part) }));
|
|
98
|
+
}
|
|
99
|
+
/** A move with its capture's x light, as the move list writes it: the piece and the squares stand out (Stefano, for readers with ADHD). */
|
|
100
|
+
function Takes({ move }) {
|
|
101
|
+
return _jsx(_Fragment, { children: move.split("x").map((part, index) => index === 0 ? part : [_jsx("span", { class: "takes", children: "x" }, index), part]) });
|
|
102
|
+
}
|
|
103
|
+
/** The square a word names: a square, or where a move goes, the last square in it; none for a castling. */
|
|
104
|
+
function squareIn(word) {
|
|
105
|
+
return /[a-h][1-8](?!.*[a-h][1-8])/.exec(word)?.[0];
|
|
106
|
+
}
|
|
107
|
+
/** The AI's word on the whole game (D-69), in the Torretta's bubble at the start of the game: a paragraph, and its points as a list. */
|
|
108
|
+
function GameReview({ by, summary, text }) {
|
|
109
|
+
const [lead = "", ...points] = summary.split(/\s*•\s+/);
|
|
110
|
+
return (_jsxs("section", { class: "say review", "aria-label": text.reviewBy(by), children: [_jsxs("p", { class: "head", children: [_jsx("svg", { class: "icon", viewBox: "0 0 24 24", "aria-hidden": "true", children: _jsx("path", { d: "M12 4V20M8 20H16M5 7H19M5 7L2.5 13A2.5 2 0 0 0 7.5 13ZM19 7L16.5 13A2.5 2 0 0 0 21.5 13Z" }) }), text.reviewBy(by)] }), lead === "" ? null : (_jsx("p", { children: _jsx(Marked, { text: lead }) })), points.length === 0 ? null : (_jsx("ul", { children: points.map((point, index) => (_jsx("li", { children: _jsx(Marked, { text: point }) }, index))) }))] }));
|
|
111
|
+
}
|
|
119
112
|
function RailPlayer({ place, picture, name, side, moves, unread = false }) {
|
|
120
113
|
return (_jsxs("div", { class: `rail-player ${place}${moves ? " moving" : ""}`, children: [_jsx("span", { class: `face${unread ? " unread" : ""}`, children: picture }), _jsxs("span", { class: "rail-name", children: [name, " ", side === undefined ? null : _jsxs("span", { class: "note", children: ["\u00B7 ", side] })] })] }));
|
|
121
114
|
}
|
package/dist/page/text.js
CHANGED
|
@@ -31,6 +31,7 @@ const english = {
|
|
|
31
31
|
marksColour: "Arrows and marked squares",
|
|
32
32
|
play: "Play",
|
|
33
33
|
dots: "Dots on the legal moves",
|
|
34
|
+
squareNames: "The square's name under the pointer",
|
|
34
35
|
explain: "Explain the moves refused",
|
|
35
36
|
bookBadges: "Mark the book moves",
|
|
36
37
|
helps: "The AI teaches as you play",
|
|
@@ -39,7 +40,7 @@ const english = {
|
|
|
39
40
|
names: {
|
|
40
41
|
nitida: "Nitida",
|
|
41
42
|
torretta: "Torretta",
|
|
42
|
-
|
|
43
|
+
capablanca: "Capablanca",
|
|
43
44
|
azzurro: "Blue",
|
|
44
45
|
verde: "Green",
|
|
45
46
|
noce: "Walnut",
|
|
@@ -61,7 +62,10 @@ const english = {
|
|
|
61
62
|
moves: "Moves",
|
|
62
63
|
steps: { first: "Start", back: "Previous move", forward: "Next move", last: "Back to the game" },
|
|
63
64
|
noGame: "No game yet: press + to start one, or ask for one in the chat.",
|
|
64
|
-
|
|
65
|
+
foldCard: "Fold the card",
|
|
66
|
+
openCard: "Open the card",
|
|
67
|
+
saveMoves: "Moves-only PGN",
|
|
68
|
+
saveMovesHint: "The moves alone, to open on Lichess or chess.com",
|
|
65
69
|
noGameNow: "No game in progress",
|
|
66
70
|
analysing: "Analysis in progress",
|
|
67
71
|
badges: {
|
|
@@ -78,6 +82,18 @@ const english = {
|
|
|
78
82
|
},
|
|
79
83
|
reviewBy: (name) => `${name}'s review`,
|
|
80
84
|
drawn: { green: "better", red: "threat", yellow: "another way", blue: "plan" },
|
|
85
|
+
lead: {
|
|
86
|
+
hint: "Who is ahead, in pawns, as the AI estimates it: Chesspal does not compute it",
|
|
87
|
+
chart: "How the game went",
|
|
88
|
+
chartHint: "Who was ahead move by move, as the AI estimated it: click to go to that move",
|
|
89
|
+
even: "Even",
|
|
90
|
+
none: "No estimate yet",
|
|
91
|
+
earlier: "Estimated before the last move",
|
|
92
|
+
drawn: "Drawn on the board",
|
|
93
|
+
ahead: (side, pawns) => `${side === "white" ? "White" : "Black"} ahead by ${pawns} pawns`,
|
|
94
|
+
mate: (side, moves) => `${side === "white" ? "White" : "Black"} mates in ${moves}`,
|
|
95
|
+
mated: (side) => `${side === "white" ? "White" : "Black"} is mated`,
|
|
96
|
+
},
|
|
81
97
|
reviewing: (name) => `${name} is going over the game…`,
|
|
82
98
|
you: "You",
|
|
83
99
|
ai: "AI",
|
|
@@ -108,8 +124,10 @@ const english = {
|
|
|
108
124
|
canGo: "a legal move",
|
|
109
125
|
boardLabel: (turn, lastMove) => `Chessboard, ${english.toMove(turn)}${lastMove === undefined ? "" : `, last move ${lastMove}`}`,
|
|
110
126
|
clearChat: (name) => `Before a new game, clear your chat with ${name}: in the window where you opened ${name}, not here, write /clear, then a message such as "new game". A clean chat plays faster.`,
|
|
127
|
+
outdated: (name) => `Chesspal has been updated, but this folder still has its old files: close the chat with ${name}, run chesspal init in this folder, and open a new chat.`,
|
|
111
128
|
offline: (name) => `${name} is not connected. Write it a message in the window where you opened ${name}, not in this page's chat: the page connects again by itself.`,
|
|
112
129
|
startClocks: "Start",
|
|
130
|
+
thinking: { move: "Thinking about its move", ponder: "Thinking while you play" },
|
|
113
131
|
asleep: (name) => `${name} is not listening: write a message, such as "hi", in the window where you opened ${name}, not here. Its clock waits until it answers.`,
|
|
114
132
|
commandHere: (name) => `/clear and the other commands go in the window where you opened ${name}, not here.`,
|
|
115
133
|
refused: {
|
|
@@ -183,6 +201,8 @@ const english = {
|
|
|
183
201
|
yourPicture: "Your picture: change it",
|
|
184
202
|
avatars: { "short-hair": "Short hair", bun: "Bun", glasses: "Glasses", beanie: "Beanie", beard: "Beard", curls: "Curls", moustache: "Moustache", "silver-bob": "Silver bob", cat: "Cat", owl: "Owl" },
|
|
185
203
|
whilePlaying: "Finish the game, or resign, before changing player.",
|
|
204
|
+
username: "your username",
|
|
205
|
+
accountTitle: "With your name there, a game you load from there knows which side is yours.",
|
|
186
206
|
badImage: "That picture won't open: try another photo (the ones from a phone usually work).",
|
|
187
207
|
},
|
|
188
208
|
start: {
|
|
@@ -208,21 +228,45 @@ const english = {
|
|
|
208
228
|
note: "The game is kept to study; the AI goes over it with you in the chat.",
|
|
209
229
|
start: "Analyse",
|
|
210
230
|
yours: "Your analyses",
|
|
211
|
-
bring: "
|
|
231
|
+
bring: "Load a game",
|
|
232
|
+
bringNote: "a PGN played elsewhere, pasted or from a file",
|
|
233
|
+
search: "Names, models, openings…",
|
|
234
|
+
noMatch: "No game found",
|
|
212
235
|
reviewed: "reviewed",
|
|
213
236
|
unreviewed: "to review",
|
|
214
237
|
moves: (count) => `${count} ${count === 1 ? "move" : "moves"}`,
|
|
215
|
-
|
|
238
|
+
outcome: { won: "won", lost: "lost", drawn: "drawn" },
|
|
239
|
+
more: "More",
|
|
240
|
+
redo: "Analyse again",
|
|
241
|
+
redoNote: "with your chat's model and effort",
|
|
242
|
+
unreview: "Delete the analysis",
|
|
243
|
+
unreviewNote: "the game stays, to review",
|
|
244
|
+
remove: "Delete the game",
|
|
245
|
+
askRedo: (game, by) => ({
|
|
246
|
+
question: `Analyse ${game} again?`,
|
|
247
|
+
note: `${by === undefined ? "The review" : `The review by ${by}`} is deleted; your chat's analyst writes it again, with the model and effort it has now.`,
|
|
248
|
+
yes: "Analyse again",
|
|
249
|
+
}),
|
|
250
|
+
askUnreview: (game) => ({ question: `Delete the analysis of ${game}?`, note: "Its badges, notes and the coach's judgments go; the game stays.", yes: "Delete" }),
|
|
251
|
+
askRemove: (game, when) => ({ question: `Delete the game ${game}${when === undefined ? "" : ` of ${when}`}?`, note: "With its analysis. It cannot be undone.", yes: "Delete" }),
|
|
252
|
+
cancel: "Cancel",
|
|
253
|
+
download: "Annotated PGN",
|
|
254
|
+
downloadHint: "The game with the review's comments and judgments",
|
|
216
255
|
analyseIt: "Analyse the game",
|
|
217
256
|
analyseLast: "Analyse the last game",
|
|
218
257
|
},
|
|
219
258
|
helpsCard: {
|
|
220
259
|
title: "Helps",
|
|
260
|
+
coach: "The coach",
|
|
261
|
+
showHint: "Show hint",
|
|
262
|
+
hideHint: "Hide hint",
|
|
263
|
+
drawn: { green: "idea", red: "threat", yellow: "line", blue: "target" },
|
|
221
264
|
tactics: "Tactics",
|
|
222
265
|
strategy: "Strategy",
|
|
223
266
|
map: "Map",
|
|
224
267
|
mapHint: "Hold it, or the M key, to see who controls each square; on a phone, a touch turns it on and off",
|
|
225
|
-
|
|
268
|
+
bare: "Hide the drawings",
|
|
269
|
+
bareHint: "Hold it to see the board without the arrows, the marked squares and the helps' signs; on a phone, a touch hides them and shows them again",
|
|
226
270
|
attackers: "attackers",
|
|
227
271
|
defenders: "defenders",
|
|
228
272
|
undefended: "no defender",
|
|
@@ -231,8 +275,20 @@ const english = {
|
|
|
231
275
|
pinnedTo: (letter) => `pinned to the ${englishNames[letter]}`,
|
|
232
276
|
pinnedBy: (letter) => `by the ${englishNames[letter]}`,
|
|
233
277
|
nothingAtRisk: "No piece at risk, no pins.",
|
|
234
|
-
|
|
278
|
+
line: (kind, side, you, toMove) => {
|
|
279
|
+
const name = side === "white" ? "White" : "Black";
|
|
280
|
+
if (you === undefined) {
|
|
281
|
+
return kind === "risk" ? `${name}'s pieces at risk` : kind === "pin" ? `${name}'s pinned pieces` : `${name}'s checks${toMove ? "" : `, if it were ${name}'s move`}`;
|
|
282
|
+
}
|
|
283
|
+
if (kind === "check") {
|
|
284
|
+
return side === you ? `Checks you ${toMove ? "can" : "could"} give` : `Checks the opponent ${toMove ? "can" : "could"} give you`;
|
|
285
|
+
}
|
|
286
|
+
return `${side === you ? "Your" : "The opponent's"} ${kind === "risk" ? "pieces at risk" : "pinned pieces"}`;
|
|
287
|
+
},
|
|
235
288
|
loose: "Pieces neither attacked nor defended",
|
|
289
|
+
yours: "yours",
|
|
290
|
+
theirs: "the opponent's",
|
|
291
|
+
you: "(you)",
|
|
236
292
|
white: "White",
|
|
237
293
|
black: "Black",
|
|
238
294
|
rows: {
|
|
@@ -248,14 +304,17 @@ const english = {
|
|
|
248
304
|
bishopPair: ["Bishop pair", "Both bishops still on the board."],
|
|
249
305
|
space: ["Space (squares in the enemy's half)", "How many squares of the enemy's half one's pieces attack."],
|
|
250
306
|
undeveloped: ["Minor pieces not developed", "Knights and bishops still on their first squares."],
|
|
251
|
-
castled: ["Castling", "How it castled;
|
|
307
|
+
castled: ["Castling", "How it castled; a dash while it still can, a cross once the king or the rooks have moved."],
|
|
252
308
|
kingAttacks: ["Enemy attacks around the king", "How many enemy attacks fall on the squares next to the king."],
|
|
253
309
|
},
|
|
310
|
+
groups: { pawns: "Pawns", pieces: "Pieces", king: "King" },
|
|
254
311
|
yes: "yes",
|
|
255
312
|
notYet: "not yet",
|
|
256
313
|
noMore: "no more",
|
|
257
|
-
phases: { opening: "
|
|
258
|
-
openFiles:
|
|
314
|
+
phases: { opening: "Opening", middlegame: "Middlegame", endgame: "Endgame" },
|
|
315
|
+
openFiles: "Open files",
|
|
316
|
+
control: "Squares controlled",
|
|
317
|
+
both: "both",
|
|
259
318
|
controlled: (white, black, both) => `Squares only White's ${white}, only Black's ${black}, both ${both}`,
|
|
260
319
|
oppositeBishops: "Bishops of opposite colours",
|
|
261
320
|
repetitions: (times) => `This position has stood ${times} times`,
|
|
@@ -291,6 +350,7 @@ const italian = {
|
|
|
291
350
|
marksColour: "Frecce e case segnate",
|
|
292
351
|
play: "Gioco",
|
|
293
352
|
dots: "Pallini sulle mosse legali",
|
|
353
|
+
squareNames: "Il nome della casa sotto il puntatore",
|
|
294
354
|
explain: "Spiega le mosse vietate",
|
|
295
355
|
bookBadges: "Segna le mosse da libro",
|
|
296
356
|
helps: "L'AI ti insegna mentre giochi",
|
|
@@ -299,7 +359,7 @@ const italian = {
|
|
|
299
359
|
names: {
|
|
300
360
|
nitida: "Nitida",
|
|
301
361
|
torretta: "Torretta",
|
|
302
|
-
|
|
362
|
+
capablanca: "Capablanca",
|
|
303
363
|
azzurro: "Azzurro",
|
|
304
364
|
verde: "Verde",
|
|
305
365
|
noce: "Noce",
|
|
@@ -321,7 +381,10 @@ const italian = {
|
|
|
321
381
|
moves: "Mosse",
|
|
322
382
|
steps: { first: "Inizio", back: "Mossa precedente", forward: "Mossa successiva", last: "Torna alla partita" },
|
|
323
383
|
noGame: "Nessuna partita: premi + per iniziarne una, o chiedila nella chat.",
|
|
324
|
-
|
|
384
|
+
foldCard: "Chiudi la scheda",
|
|
385
|
+
openCard: "Apri la scheda",
|
|
386
|
+
saveMoves: "PGN solo mosse",
|
|
387
|
+
saveMovesHint: "Solo le mosse, da aprire su Lichess o chess.com",
|
|
325
388
|
noGameNow: "Nessuna partita in corso",
|
|
326
389
|
analysing: "Analisi in corso",
|
|
327
390
|
badges: {
|
|
@@ -338,6 +401,18 @@ const italian = {
|
|
|
338
401
|
},
|
|
339
402
|
reviewBy: (name) => `Il giudizio di ${name}`,
|
|
340
403
|
drawn: { green: "meglio", red: "minaccia", yellow: "altra via", blue: "piano" },
|
|
404
|
+
lead: {
|
|
405
|
+
hint: "Chi è avanti, in pedoni, secondo la stima dell'AI: Chesspal non lo calcola",
|
|
406
|
+
chart: "Andamento della partita",
|
|
407
|
+
chartHint: "Chi era avanti mossa per mossa, secondo la stima dell'AI: clicca per andare a quella mossa",
|
|
408
|
+
even: "Pari",
|
|
409
|
+
none: "Ancora nessuna stima",
|
|
410
|
+
earlier: "Stimata prima dell'ultima mossa",
|
|
411
|
+
drawn: "Patta sulla scacchiera",
|
|
412
|
+
ahead: (side, pawns) => `Il ${side === "white" ? "Bianco" : "Nero"} è avanti di ${pawns} pedoni`,
|
|
413
|
+
mate: (side, moves) => `Il ${side === "white" ? "Bianco" : "Nero"} dà matto in ${moves}`,
|
|
414
|
+
mated: (side) => `Matto al ${side === "white" ? "Bianco" : "Nero"}`,
|
|
415
|
+
},
|
|
341
416
|
reviewing: (name) => `${name} sta analizzando la partita…`,
|
|
342
417
|
you: "Tu",
|
|
343
418
|
ai: "AI",
|
|
@@ -368,8 +443,10 @@ const italian = {
|
|
|
368
443
|
canGo: "mossa possibile",
|
|
369
444
|
boardLabel: (turn, lastMove) => `Scacchiera, ${italian.toMove(turn)}${lastMove === undefined ? "" : `, ultima mossa ${lastMove}`}`,
|
|
370
445
|
clearChat: (name) => `Prima di una nuova partita azzera la conversazione con ${name}: nella finestra dove hai aperto ${name}, non qui, scrivi /clear e poi un messaggio, per esempio "nuova partita". Con la chat pulita l'AI gioca più veloce.`,
|
|
446
|
+
outdated: (name) => `Chesspal è stato aggiornato, ma questa cartella ha ancora i file di prima: chiudi la chat con ${name}, esegui chesspal init in questa cartella e apri una chat nuova.`,
|
|
371
447
|
offline: (name) => `${name} è scollegato. Scrivigli un messaggio nella finestra dove hai aperto ${name}, non nella chat di questa pagina: la pagina si ricollega da sola.`,
|
|
372
448
|
startClocks: "Inizia",
|
|
449
|
+
thinking: { move: "Sta pensando alla sua mossa", ponder: "Pensa mentre giochi tu" },
|
|
373
450
|
asleep: (name) => `${name} non ti sta ascoltando: scrivi un messaggio, per esempio "ciao", nella finestra dove hai aperto ${name}, non qui. Il suo orologio aspetta che risponda.`,
|
|
374
451
|
commandHere: (name) => `/clear e gli altri comandi vanno scritti nella finestra dove hai aperto ${name}, non qui.`,
|
|
375
452
|
refused: {
|
|
@@ -444,6 +521,8 @@ const italian = {
|
|
|
444
521
|
yourPicture: "La tua immagine: cambiala",
|
|
445
522
|
avatars: { "short-hair": "Capelli corti", bun: "Chignon", glasses: "Occhiali", beanie: "Berretto", beard: "Barba", curls: "Ricci", moustache: "Baffi", "silver-bob": "Caschetto grigio", cat: "Gatto", owl: "Gufo" },
|
|
446
523
|
whilePlaying: "Finisci la partita, o abbandona, prima di cambiare giocatore.",
|
|
524
|
+
username: "il tuo nome utente",
|
|
525
|
+
accountTitle: "Col tuo nome lì, una partita che carichi da lì sa qual è la tua parte.",
|
|
447
526
|
badImage: "Questa immagine non si apre: prova con un'altra foto (quelle del telefono di solito vanno bene).",
|
|
448
527
|
},
|
|
449
528
|
start: {
|
|
@@ -469,31 +548,67 @@ const italian = {
|
|
|
469
548
|
note: "La partita resta tra quelle da studiare; l'AI la commenta con te nella chat.",
|
|
470
549
|
start: "Analizza",
|
|
471
550
|
yours: "Le tue analisi",
|
|
472
|
-
bring: "
|
|
551
|
+
bring: "Carica una partita",
|
|
552
|
+
bringNote: "un PGN giocato altrove, incollato o da file",
|
|
553
|
+
search: "Nomi, modelli, aperture…",
|
|
554
|
+
noMatch: "Nessuna partita trovata",
|
|
473
555
|
reviewed: "commentata",
|
|
474
556
|
unreviewed: "da commentare",
|
|
475
557
|
moves: (count) => `${count} ${count === 1 ? "mossa" : "mosse"}`,
|
|
476
|
-
|
|
558
|
+
outcome: { won: "vinta", lost: "persa", drawn: "patta" },
|
|
559
|
+
more: "Altro",
|
|
560
|
+
redo: "Rifai l'analisi",
|
|
561
|
+
redoNote: "con il modello e l'effort della tua chat",
|
|
562
|
+
unreview: "Elimina l'analisi",
|
|
563
|
+
unreviewNote: "la partita resta, da commentare",
|
|
564
|
+
remove: "Elimina la partita",
|
|
565
|
+
askRedo: (game, by) => ({
|
|
566
|
+
question: `Rifare l'analisi di ${game}?`,
|
|
567
|
+
note: `${by === undefined ? "L'analisi" : `L'analisi di ${by}`} si cancella; la rifà l'analista della tua chat, col modello e l'effort che ha ora.`,
|
|
568
|
+
yes: "Rifai",
|
|
569
|
+
}),
|
|
570
|
+
askUnreview: (game) => ({ question: `Eliminare l'analisi di ${game}?`, note: "Bollini, note e giudizi dell'allenatore si cancellano; la partita resta.", yes: "Elimina" }),
|
|
571
|
+
askRemove: (game, when) => ({ question: `Eliminare la partita ${game}${when === undefined ? "" : ` del ${when}`}?`, note: "Con la sua analisi. Non si può annullare.", yes: "Elimina" }),
|
|
572
|
+
cancel: "Annulla",
|
|
573
|
+
download: "PGN annotato",
|
|
574
|
+
downloadHint: "La partita con i commenti e i giudizi della revisione",
|
|
477
575
|
analyseIt: "Analizza la partita",
|
|
478
576
|
analyseLast: "Analizza l'ultima partita",
|
|
479
577
|
},
|
|
480
578
|
helpsCard: {
|
|
481
579
|
title: "Aiuti",
|
|
580
|
+
coach: "L'allenatore",
|
|
581
|
+
showHint: "Mostra il suggerimento",
|
|
582
|
+
hideHint: "Nascondi il suggerimento",
|
|
583
|
+
drawn: { green: "idea", red: "minaccia", yellow: "linea", blue: "obiettivo" },
|
|
482
584
|
tactics: "Tattica",
|
|
483
585
|
strategy: "Strategia",
|
|
484
586
|
map: "Mappa",
|
|
485
587
|
mapHint: "Tienilo premuto, o tieni premuto il tasto M, per vedere chi controlla ogni casa; sul telefono un tocco la accende e la spegne",
|
|
486
|
-
|
|
588
|
+
bare: "Nascondi i disegni",
|
|
589
|
+
bareHint: "Tienilo premuto per vedere la scacchiera senza frecce, case segnate e segni degli aiuti; sul telefono un tocco li nasconde e li rimostra",
|
|
487
590
|
attackers: "attaccanti",
|
|
488
591
|
defenders: "difensori",
|
|
489
592
|
undefended: "nessun difensore",
|
|
490
|
-
cheaper: "un attaccante vale meno",
|
|
593
|
+
cheaper: "un attaccante vale meno di lui",
|
|
491
594
|
outnumbered: "più attaccanti che difensori",
|
|
492
595
|
pinnedTo: (letter) => `davanti ${italianWith("a", letter)}`,
|
|
493
596
|
pinnedBy: (letter) => italianWith("da", letter),
|
|
494
597
|
nothingAtRisk: "Nessun pezzo in pericolo, nessuna inchiodatura.",
|
|
495
|
-
|
|
598
|
+
line: (kind, side, you, toMove) => {
|
|
599
|
+
const name = side === "white" ? "Bianco" : "Nero";
|
|
600
|
+
if (you === undefined) {
|
|
601
|
+
return kind === "risk" ? `Pezzi del ${name} in pericolo` : kind === "pin" ? `Pezzi del ${name} inchiodati` : `Scacchi del ${name}${toMove ? "" : ", se toccasse a lui"}`;
|
|
602
|
+
}
|
|
603
|
+
if (kind === "check") {
|
|
604
|
+
return side === you ? `Scacchi che ${toMove ? "puoi" : "potresti"} dare` : `Scacchi che l'avversario ${toMove ? "può" : "potrebbe"} darti`;
|
|
605
|
+
}
|
|
606
|
+
return `${side === you ? "I tuoi pezzi" : "I pezzi avversari"} ${kind === "risk" ? "in pericolo" : "inchiodati"}`;
|
|
607
|
+
},
|
|
496
608
|
loose: "Pezzi né attaccati né difesi",
|
|
609
|
+
yours: "tuoi",
|
|
610
|
+
theirs: "avversari",
|
|
611
|
+
you: "(tu)",
|
|
497
612
|
white: "Bianco",
|
|
498
613
|
black: "Nero",
|
|
499
614
|
rows: {
|
|
@@ -509,14 +624,17 @@ const italian = {
|
|
|
509
624
|
bishopPair: ["Coppia degli alfieri", "Tutti e due gli alfieri ancora sulla scacchiera."],
|
|
510
625
|
space: ["Spazio (case nella metà avversaria)", "Quante case della metà avversaria attaccano i propri pezzi."],
|
|
511
626
|
undeveloped: ["Pezzi minori non sviluppati", "Cavalli e alfieri ancora sulle case di partenza."],
|
|
512
|
-
castled: ["Arrocco", "Come ha arroccato;
|
|
627
|
+
castled: ["Arrocco", "Come ha arroccato; un trattino finché può ancora farlo, una croce quando il re o le torri si sono già mossi."],
|
|
513
628
|
kingAttacks: ["Attacchi nemici attorno al re", "Quanti attacchi nemici cadono sulle case accanto al re."],
|
|
514
629
|
},
|
|
630
|
+
groups: { pawns: "Pedoni", pieces: "Pezzi", king: "Re" },
|
|
515
631
|
yes: "sì",
|
|
516
632
|
notYet: "non ancora",
|
|
517
633
|
noMore: "non più",
|
|
518
|
-
phases: { opening: "
|
|
519
|
-
openFiles:
|
|
634
|
+
phases: { opening: "Apertura", middlegame: "Mediogioco", endgame: "Finale" },
|
|
635
|
+
openFiles: "Colonne aperte",
|
|
636
|
+
control: "Case controllate",
|
|
637
|
+
both: "tutti e due",
|
|
520
638
|
controlled: (white, black, both) => `Case solo del Bianco ${white}, solo del Nero ${black}, di tutti e due ${both}`,
|
|
521
639
|
oppositeBishops: "Alfieri di colore contrario",
|
|
522
640
|
repetitions: (times) => `Questa posizione si è vista ${times} volte`,
|