chesspal 0.3.1 → 0.3.3

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.
Files changed (185) hide show
  1. package/README.md +1 -1
  2. package/dist/cli/cli.js +6 -6
  3. package/dist/commands/{analyse-game.d.ts → analysis/analyse.d.ts} +2 -2
  4. package/dist/commands/{analyse-game.js → analysis/analyse.js} +7 -11
  5. package/dist/commands/{annotate-game.d.ts → analysis/annotate.d.ts} +1 -1
  6. package/dist/commands/{annotate-game.js → analysis/annotate.js} +6 -9
  7. package/dist/commands/{delete-review.d.ts → analysis/delete-review.d.ts} +1 -1
  8. package/dist/commands/{delete-review.js → analysis/delete-review.js} +5 -5
  9. package/dist/commands/analysis/index.d.ts +4 -0
  10. package/dist/commands/analysis/index.js +5 -0
  11. package/dist/commands/{study-games.d.ts → analysis/study-games.d.ts} +1 -1
  12. package/dist/commands/{study-games.js → analysis/study-games.js} +4 -5
  13. package/dist/commands/{agents.d.ts → answers/agents.d.ts} +4 -4
  14. package/dist/commands/{agents.js → answers/agents.js} +13 -9
  15. package/dist/commands/{clock.d.ts → answers/clock.d.ts} +2 -2
  16. package/dist/commands/{clock.js → answers/clock.js} +2 -2
  17. package/dist/commands/{drawings.d.ts → answers/drawings.d.ts} +1 -1
  18. package/dist/commands/{drawings.js → answers/drawings.js} +1 -1
  19. package/dist/commands/answers/index.d.ts +12 -0
  20. package/dist/commands/answers/index.js +14 -0
  21. package/dist/commands/{lead-input.d.ts → answers/lead-input.d.ts} +1 -1
  22. package/dist/commands/{lead-input.js → answers/lead-input.js} +1 -1
  23. package/dist/commands/{answer-lines.d.ts → answers/lines.d.ts} +2 -2
  24. package/dist/commands/{answer-lines.js → answers/lines.js} +4 -4
  25. package/dist/commands/{opening-book.d.ts → answers/opening-book.d.ts} +1 -1
  26. package/dist/commands/{opening-book.js → answers/opening-book.js} +3 -3
  27. package/dist/commands/{play-move.d.ts → answers/play-move.d.ts} +2 -2
  28. package/dist/commands/{play-move.js → answers/play-move.js} +3 -3
  29. package/dist/commands/{say.d.ts → answers/say.d.ts} +3 -3
  30. package/dist/commands/{say.js → answers/say.js} +4 -4
  31. package/dist/commands/{speech.js → answers/speech.js} +1 -1
  32. package/dist/commands/{study.d.ts → answers/study.d.ts} +3 -3
  33. package/dist/commands/{study.js → answers/study.js} +3 -3
  34. package/dist/commands/{game-summary.d.ts → answers/summary.d.ts} +2 -2
  35. package/dist/commands/{game-summary.js → answers/summary.js} +4 -4
  36. package/dist/commands/{view.d.ts → answers/view.d.ts} +1 -1
  37. package/dist/commands/{ai-move.d.ts → game/ai-move.d.ts} +2 -2
  38. package/dist/commands/{ai-move.js → game/ai-move.js} +6 -11
  39. package/dist/commands/{coach.d.ts → game/coach.d.ts} +1 -1
  40. package/dist/commands/{coach.js → game/coach.js} +7 -13
  41. package/dist/commands/{draw-offer.d.ts → game/draw-offer.d.ts} +1 -1
  42. package/dist/commands/{draw-offer.js → game/draw-offer.js} +4 -4
  43. package/dist/commands/{end-game.d.ts → game/end.d.ts} +2 -2
  44. package/dist/commands/{end-game.js → game/end.js} +5 -9
  45. package/dist/commands/{export-game.d.ts → game/export.d.ts} +1 -1
  46. package/dist/commands/{export-game.js → game/export.js} +4 -4
  47. package/dist/commands/game/index.d.ts +11 -0
  48. package/dist/commands/game/index.js +13 -0
  49. package/dist/commands/{levels.d.ts → game/levels.d.ts} +3 -3
  50. package/dist/commands/{levels.js → game/levels.js} +3 -3
  51. package/dist/commands/{look.d.ts → game/look.d.ts} +3 -4
  52. package/dist/commands/{look.js → game/look.js} +5 -10
  53. package/dist/commands/{new-game.d.ts → game/new.d.ts} +3 -4
  54. package/dist/commands/{new-game.js → game/new.js} +17 -13
  55. package/dist/commands/{page-link.d.ts → game/page-link.d.ts} +1 -1
  56. package/dist/commands/{player-move.d.ts → game/player-move.d.ts} +2 -2
  57. package/dist/commands/{player-move.js → game/player-move.js} +4 -8
  58. package/dist/commands/{ponder.d.ts → game/ponder.d.ts} +3 -3
  59. package/dist/commands/{ponder.js → game/ponder.js} +6 -9
  60. package/dist/commands/{position.d.ts → game/position.d.ts} +2 -2
  61. package/dist/commands/{position.js → game/position.js} +5 -7
  62. package/dist/commands/{status.d.ts → game/status.d.ts} +2 -4
  63. package/dist/commands/{status.js → game/status.js} +12 -17
  64. package/dist/commands/index.d.ts +6 -17
  65. package/dist/commands/index.js +11 -38
  66. package/dist/commands/{delete-game.d.ts → profiles/delete-game.d.ts} +1 -1
  67. package/dist/commands/{delete-game.js → profiles/delete-game.js} +3 -3
  68. package/dist/commands/profiles/index.d.ts +4 -0
  69. package/dist/commands/profiles/index.js +5 -0
  70. package/dist/commands/{past-games.d.ts → profiles/past-games.d.ts} +1 -1
  71. package/dist/commands/{past-games.js → profiles/past-games.js} +5 -5
  72. package/dist/commands/{profiles.d.ts → profiles/profiles.d.ts} +7 -7
  73. package/dist/commands/{profiles.js → profiles/profiles.js} +4 -4
  74. package/dist/commands/{ratings.d.ts → profiles/ratings.d.ts} +1 -1
  75. package/dist/commands/{ratings.js → profiles/ratings.js} +2 -2
  76. package/dist/commands/{context.js → registry/context.js} +2 -2
  77. package/dist/commands/registry/index.d.ts +2 -0
  78. package/dist/commands/registry/index.js +3 -0
  79. package/dist/commands/setup/index.d.ts +2 -0
  80. package/dist/commands/setup/index.js +3 -0
  81. package/dist/commands/{init.d.ts → setup/init.d.ts} +1 -1
  82. package/dist/commands/{init.js → setup/init.js} +2 -3
  83. package/dist/commands/{instructions.d.ts → setup/instructions.d.ts} +2 -2
  84. package/dist/commands/{instructions.js → setup/instructions.js} +3 -3
  85. package/dist/commands/{ai-say.d.ts → talk/ai-say.d.ts} +2 -3
  86. package/dist/commands/{ai-say.js → talk/ai-say.js} +5 -9
  87. package/dist/commands/talk/index.d.ts +2 -0
  88. package/dist/commands/talk/index.js +3 -0
  89. package/dist/commands/{player-say.d.ts → talk/player-say.d.ts} +1 -1
  90. package/dist/commands/{player-say.js → talk/player-say.js} +4 -4
  91. package/dist/page/app/app.js +53 -21
  92. package/dist/page/app/served.js +15 -3
  93. package/dist/page/avatars/torretta.js +10 -3
  94. package/dist/page/dialogs/dialogs.css +10 -0
  95. package/dist/page/dialogs/profiles.js +1 -5
  96. package/dist/page/dialogs/settings.js +18 -4
  97. package/dist/page/game/column.js +1 -1
  98. package/dist/page/game/game.css +26 -3
  99. package/dist/page/guide/blocks.js +13 -2
  100. package/dist/page/guide/credits.js +6 -0
  101. package/dist/page/guide/drawings/analysis.js +13 -0
  102. package/dist/page/guide/drawings/drawings.css +329 -0
  103. package/dist/page/guide/drawings/drawings.js +15 -0
  104. package/dist/page/guide/drawings/game.js +15 -0
  105. package/dist/page/guide/drawings/helps.js +13 -0
  106. package/dist/page/guide/drawings/how-it-works.js +13 -0
  107. package/dist/page/guide/drawings/parts.js +103 -0
  108. package/dist/page/guide/drawings/players.js +19 -0
  109. package/dist/page/guide/drawings/talk.js +9 -0
  110. package/dist/page/guide/en.md +39 -25
  111. package/dist/page/guide/guide.css +123 -91
  112. package/dist/page/guide/guide.js +47 -25
  113. package/dist/page/guide/it.md +39 -25
  114. package/dist/page/guide/markdown.js +5 -0
  115. package/dist/page/helps/helps.css +201 -88
  116. package/dist/page/helps/helps.js +50 -31
  117. package/dist/page/helps/view.js +13 -3
  118. package/dist/page/{guide/foot.js → layout/footer.js} +7 -8
  119. package/dist/page/layout/header.js +5 -3
  120. package/dist/page/layout/layout.css +114 -10
  121. package/dist/page/layout/window.js +6 -26
  122. package/dist/page/main.js +1 -1
  123. package/dist/page/pieces/pieces.js +5 -2
  124. package/dist/page/style.css +1 -0
  125. package/dist/page/table/table.css +69 -0
  126. package/dist/page/table/update.js +82 -0
  127. package/dist/page/table/window.js +6 -5
  128. package/dist/page/talk/chat.css +6 -6
  129. package/dist/page/talk/talk.css +17 -67
  130. package/dist/page/talk/talk.js +6 -6
  131. package/dist/page/talk/voice.js +12 -0
  132. package/dist/page/text.js +78 -20
  133. package/dist/page/theme.css +2 -0
  134. package/dist/server/{bell.js → bell/bell.js} +17 -4
  135. package/dist/server/bell/index.d.ts +1 -0
  136. package/dist/server/bell/index.js +2 -0
  137. package/dist/server/{caller.d.ts → mcp/caller.d.ts} +1 -1
  138. package/dist/server/{caller.js → mcp/caller.js} +1 -1
  139. package/dist/server/mcp/index.d.ts +1 -0
  140. package/dist/server/mcp/index.js +2 -0
  141. package/dist/server/{mcp.d.ts → mcp/mcp.d.ts} +1 -1
  142. package/dist/server/{mcp.js → mcp/mcp.js} +9 -9
  143. package/dist/server/page/attach.js +8 -3
  144. package/dist/server/page/game.js +19 -3
  145. package/dist/server/page/http.d.ts +1 -1
  146. package/dist/server/page/index.d.ts +3 -0
  147. package/dist/server/page/index.js +3 -0
  148. package/dist/server/page/page.d.ts +12 -3
  149. package/dist/server/page/page.js +26 -5
  150. package/dist/server/page/table.d.ts +7 -1
  151. package/dist/server/page/table.js +79 -3
  152. package/dist/server/page/update.d.ts +18 -0
  153. package/dist/server/page/update.js +40 -0
  154. package/dist/server/table/browser.d.ts +1 -1
  155. package/dist/server/table/browser.js +1 -1
  156. package/dist/server/table/hosts/chats.d.ts +1 -1
  157. package/dist/server/table/hosts/chats.js +2 -2
  158. package/dist/server/table/hosts/index.d.ts +1 -1
  159. package/dist/server/table/hosts/index.js +1 -1
  160. package/dist/server/table/hosts/play.d.ts +8 -1
  161. package/dist/server/table/hosts/play.js +40 -4
  162. package/dist/server/table/hosts/seat.d.ts +5 -1
  163. package/dist/server/table/hosts/seat.js +1 -1
  164. package/dist/server/table/index.d.ts +3 -2
  165. package/dist/server/table/index.js +3 -2
  166. package/dist/server/table/launch.d.ts +5 -2
  167. package/dist/server/table/launch.js +6 -3
  168. package/dist/server/table/link.d.ts +1 -1
  169. package/dist/server/table/link.js +3 -3
  170. package/dist/server/table/table.d.ts +4 -5
  171. package/dist/server/table/table.js +15 -12
  172. package/dist/server/table/update.d.ts +17 -0
  173. package/dist/server/table/update.js +77 -0
  174. package/dist/sites/index.d.ts +1 -1
  175. package/dist/sites/index.js +2 -2
  176. package/dist/version.d.ts +4 -0
  177. package/dist/version.js +12 -1
  178. package/package.json +1 -1
  179. /package/dist/commands/{speech.d.ts → answers/speech.d.ts} +0 -0
  180. /package/dist/commands/{view.js → answers/view.js} +0 -0
  181. /package/dist/commands/{page-link.js → game/page-link.js} +0 -0
  182. /package/dist/commands/{context.d.ts → registry/context.d.ts} +0 -0
  183. /package/dist/commands/{registry.d.ts → registry/registry.d.ts} +0 -0
  184. /package/dist/commands/{registry.js → registry/registry.js} +0 -0
  185. /package/dist/server/{bell.d.ts → bell/bell.d.ts} +0 -0
@@ -1,41 +1,63 @@
1
- import { jsx as _jsx, jsxs as _jsxs } from "preact/jsx-runtime";
2
- // The guide, from the book in the header: how to play, in the page's language (guide/<code>.md), an index of chips, its parts folding, the first two
3
- // open, and its foot; its anchors are the English guide's, so that a link finds its heading in both languages.
4
- import { useEffect, useMemo, useState } from "preact/hooks";
1
+ import { jsx as _jsx, Fragment as _Fragment, jsxs as _jsxs } from "preact/jsx-runtime";
2
+ // The guide, from the book in the header: how to play, in the page's language (guide/<code>.md), a page at a time, chosen in its index or with the arrows at
3
+ // its foot, the credits the last; its anchors are the English guide's, so that a link finds its heading in both languages.
4
+ import { useEffect, useMemo, useRef, useState } from "preact/hooks";
5
5
  import { Dialog } from "../dialogs/dialog.js";
6
6
  import { anchorOf, markdownBlocks } from "./blocks.js";
7
- import { GuideFoot } from "./foot.js";
8
- import { Blocks, Inline } from "./markdown.js";
7
+ import { GuideCredits } from "./credits.js";
8
+ import { Blocks } from "./markdown.js";
9
9
  /** The guide in its dialog. */
10
10
  export function GuideDialog({ open, onClose, text }) {
11
11
  return (_jsx(Dialog, { open: open, title: text.guide.title, onClose: onClose, text: text, children: _jsx(Guide, { text: text }) }));
12
12
  }
13
13
  function Guide({ text }) {
14
+ const words = text.guide;
14
15
  const guide = useGuide(text.language);
15
- const [open, setOpen] = useState(() => new Set([0, 1]));
16
+ const { lead, pages, anchors } = useMemo(() => guidePages(guide.own, guide.english), [guide]);
17
+ const [shown, setShown] = useState(0);
18
+ // The heading to bring into sight once its page is drawn: "" for the page's top.
16
19
  const [sought, setSought] = useState();
17
- const { lead, parts, anchors } = useMemo(() => guideParts(guide.own, guide.english), [guide]);
18
- const toggle = (index, event) => {
19
- event.preventDefault();
20
- setOpen((before) => new Set(before.has(index) ? [...before].filter((one) => one !== index) : [...before, index]));
20
+ const top = useRef(null);
21
+ const title = useRef(null);
22
+ const titles = [...pages.map((page) => page.heading.text), words.credits];
23
+ const page = pages[shown];
24
+ const show = (index, id = "") => {
25
+ setShown(index);
26
+ setSought(id);
21
27
  };
22
- // A chip of the index, or a link to a heading, opens its part and brings the heading into sight.
23
- const go = (id) => {
24
- const index = parts.findIndex((part) => [part.heading, ...part.blocks].some((block) => anchors.get(block) === id));
28
+ // A link to a heading shows its page, and the heading in it.
29
+ const go = (anchor) => {
30
+ const id = idOf(anchor);
31
+ const index = pages.findIndex((one) => [one.heading, ...one.blocks].some((block) => anchors.get(block) === id));
25
32
  if (index >= 0) {
26
- setOpen((before) => new Set([...before, index]));
27
- setSought(id);
33
+ show(index, id);
28
34
  }
29
35
  };
30
- const goToAnchor = (anchor) => go(idOf(anchor));
36
+ // A page turned: its chip in sight in the index, the focus on its title, which a screen reader says, and its top or the heading sought in sight.
31
37
  useEffect(() => {
32
38
  if (sought === undefined) {
33
39
  return;
34
40
  }
35
41
  setSought(undefined);
36
- document.getElementById(sought)?.scrollIntoView({ block: "start", behavior: matchMedia("(prefers-reduced-motion: reduce)").matches ? "auto" : "smooth" });
42
+ top.current?.querySelector(".guide-chip[aria-current]")?.scrollIntoView({ inline: "center", block: "nearest" });
43
+ title.current?.focus({ preventScroll: true });
44
+ const heading = sought === "" ? null : document.getElementById(sought);
45
+ if (heading === null) {
46
+ top.current?.closest("dialog")?.scrollTo({ top: 0 });
47
+ }
48
+ else {
49
+ heading.scrollIntoView({ block: "start" });
50
+ }
37
51
  }, [sought]);
38
- return (_jsxs("div", { class: "guide", children: [_jsx(Blocks, { blocks: lead, anchors: anchors, go: goToAnchor }), _jsx("nav", { class: "guide-index", "aria-label": text.guide.contents, children: parts.map((part) => (_jsx("button", { type: "button", class: "guide-chip", onClick: () => go(anchors.get(part.heading) ?? ""), children: _jsx(Inline, { text: part.heading.text, go: goToAnchor }) }, part.heading.text))) }), parts.map((part, index) => (_jsxs("details", { id: anchors.get(part.heading), class: "guide-part", open: open.has(index), children: [_jsx("summary", { onClick: (event) => toggle(index, event), children: _jsx("h3", { children: part.heading.text }) }), _jsx(Blocks, { blocks: part.blocks, anchors: anchors, go: goToAnchor })] }, part.heading.text))), _jsx(GuideFoot, { text: text })] }));
52
+ if (pages.length === 0) {
53
+ return _jsx("div", { class: "guide", ref: top });
54
+ }
55
+ return (_jsxs("div", { class: "guide", ref: top, children: [_jsx("nav", { class: "guide-index", "aria-label": words.contents, children: titles.map((title, index) => (_jsx("button", { type: "button", class: "guide-chip", "aria-current": index === shown ? "page" : undefined, onClick: () => show(index), children: title }, title))) }), _jsxs("article", { class: "guide-page", children: [_jsxs("div", { class: "guide-text", children: [_jsx("h3", { id: page === undefined ? undefined : anchors.get(page.heading), ref: title, tabIndex: -1, children: titles[shown] }), page === undefined ? _jsx(GuideCredits, { text: text }) : (_jsxs(_Fragment, { children: [shown === 0 ? _jsx(Blocks, { blocks: lead, anchors: anchors, go: go }) : null, _jsx(Blocks, { blocks: page.blocks, anchors: anchors, go: go })] }))] }), _jsxs("div", { class: "guide-turn", children: [shown === 0 ? null : _jsx(TurnButton, { back: true, title: titles[shown - 1] ?? "", label: words.previous, onTurn: () => show(shown - 1) }), shown === titles.length - 1 ? null : _jsx(TurnButton, { title: titles[shown + 1] ?? "", label: words.next, onTurn: () => show(shown + 1) })] })] })] }));
56
+ }
57
+ /** An arrow at a page's foot, with the title of the page it shows. */
58
+ function TurnButton({ back = false, title, label, onTurn }) {
59
+ const arrow = (_jsx("svg", { class: "icon", viewBox: "0 0 24 24", "aria-hidden": "true", children: _jsx("path", { d: back ? "M14.5 6L8.5 12L14.5 18" : "M9.5 6L15.5 12L9.5 18" }) }));
60
+ return (_jsxs("button", { type: "button", class: back ? "back" : "next", "aria-label": `${label}: ${title}`, onClick: onTurn, children: [back ? arrow : null, title, back ? null : arrow] }));
39
61
  }
40
62
  /** The guide in a language, and in English for its anchors; empty until they are read. */
41
63
  function useGuide(language) {
@@ -63,8 +85,8 @@ function guideIn(language) {
63
85
  return "";
64
86
  });
65
87
  }
66
- /** The guide's lead, the lines before its first part, its title aside; its parts; and each heading's anchor, the English one at its place. */
67
- function guideParts(own, english) {
88
+ /** The guide's lead, the lines before its first page, its title aside; its pages; and each heading's anchor, the English one at its place. */
89
+ function guidePages(own, english) {
68
90
  const blocks = markdownBlocks(own);
69
91
  const headings = blocks.filter((block) => block.kind === "heading");
70
92
  const englishHeadings = markdownBlocks(english).filter((block) => block.kind === "heading");
@@ -72,16 +94,16 @@ function guideParts(own, english) {
72
94
  const anchors = new Map(headings.map((heading, index) => [heading, idOf(anchorOf((sameShape ? englishHeadings[index] : heading)?.text ?? heading.text))]));
73
95
  const first = blocks.findIndex((block) => block.kind === "heading" && block.level === 2);
74
96
  const lead = (first < 0 ? blocks : blocks.slice(0, first)).filter((block) => !(block.kind === "heading" && block.level === 1));
75
- const parts = [];
97
+ const pages = [];
76
98
  for (const block of first < 0 ? [] : blocks.slice(first)) {
77
99
  if (block.kind === "heading" && block.level === 2) {
78
- parts.push({ heading: block, blocks: [] });
100
+ pages.push({ heading: block, blocks: [] });
79
101
  }
80
102
  else {
81
- parts.at(-1)?.blocks.push(block);
103
+ pages.at(-1)?.blocks.push(block);
82
104
  }
83
105
  }
84
- return { lead, parts, anchors };
106
+ return { lead, pages, anchors };
85
107
  }
86
108
  // A heading's id on the page, apart from the page's own.
87
109
  function idOf(anchor) {
@@ -1,9 +1,11 @@
1
1
  # Chesspal: la guida
2
2
 
3
- Con **Chesspal** giochi a scacchi contro un'**AI**, su una scacchiera vera nel browser, e impari con lei. Questa guida è per chi gioca: non serve saper programmare.
3
+ Con **Chesspal** giochi a scacchi contro un'**AI**, su una scacchiera vera, e impari con lei. Questa guida è per chi gioca: non serve saper programmare.
4
4
 
5
5
  ## Come funziona
6
6
 
7
+ ![La pagina con la scacchiera e la finestra della chat dell'AI, unite da un filo](how-it-works)
8
+
7
9
  | Chi | Cosa fa |
8
10
  |---|---|
9
11
  | **Tu** | Muovi sulla scacchiera e parli con l'AI. |
@@ -14,53 +16,65 @@ Le finestre sono due: questa **pagina**, con la scacchiera, e la **chat** dell'A
14
16
 
15
17
  Nessun motore di scacchi gioca al posto dell'AI: ogni mossa e ogni giudizio sono suoi. Chesspal controlla che ogni mossa sia legale e dice all'AI cosa c'è sulla scacchiera: i pezzi attaccati e difesi, le inchiodature, il nome dell'apertura.
16
18
 
17
- ## Avvio rapido
18
-
19
- 1. Installa **Node.js** da [nodejs.org](https://nodejs.org), la versione consigliata (LTS), e un'AI col tuo abbonamento: **Claude Code** o **Codex**.
20
- 2. Apri un terminale, la finestra dove si scrivono i comandi (su Windows il Prompt dei comandi: tasto Start, scrivi `cmd`, Invio; su macOS il Terminale), e scrivi `npm install -g chesspal`, poi `chesspal`: si apre questa pagina. La prima volta ti propone un'icona sul desktop, per aprirla con un doppio clic.
21
- 3. Premi **Claude Code** o **Codex**: la chat dell'AI si apre in una finestra sua. Tienila aperta mentre giochi.
22
- 4. Premi **Nuova partita**, scegli il colore, l'orologio e il livello dell'AI, e premi **Inizia**.
23
-
24
- ## Se ti sei perso
25
-
26
- - **L'AI non risponde**: guarda la sua finestra. Se ti sta chiedendo qualcosa, rispondi lì; se l'hai chiusa, premi di nuovo **Claude Code** o **Codex**.
27
- - **La pagina non si apre**: fai doppio clic sull'icona di Chesspal, o aprila come nell'[Avvio rapido](#quick-start).
28
- - **Le tue partite** stanno in una cartella sul tuo computer: **Chi gioca?**, dalla tua immagine in alto a destra, dice dove, e **Apri la cartella** la apre.
19
+ ### Per cominciare
29
20
 
30
- ## La chat dell'AI
31
-
32
- - La pagina apre la **chat** dell'AI coi suoi pulsanti, in una finestra a parte: lì l'AI pensa e scrive. Accanto ai pulsanti scegli il modello (la versione dell'AI) e quanto ragiona: più ragiona, più gioca lenta.
33
- - Parli con l'AI nella casella sotto il suo nome, qualche parola a ogni mossa: le legge con la tua mossa. Puoi scriverle anche nella sua finestra.
34
- - Anche una **mossa scritta** nella chat vale: `e4`, `Nf3`, con le lettere inglesi dei pezzi (K Q R B N), o a parole.
35
- - A ogni **nuova partita** la chat aperta dalla pagina riparte pulita da sola, se l'AI ha finito di pensare: una chat lunga rende l'AI più lenta.
21
+ 1. Clicca il **nome dell'AI**, in alto a sinistra, e scegli la chat fra quelle che hai sul computer: **Claude Code** o **Codex**. Si apre in una finestra sua: tienila aperta mentre giochi.
22
+ 2. Premi **Nuova partita**, scegli il colore, l'orologio e il livello dell'AI, e premi **Inizia**.
23
+ 3. Muovi: l'AI risponde sulla scacchiera, e con qualche parola sotto il suo nome.
36
24
 
37
25
  ## La partita
38
26
 
27
+ ![La scacchiera coi pallini delle mosse legali e un pezzo che si sposta](game)
28
+
39
29
  - **Muovi** trascinando un pezzo, o cliccando il pezzo e poi la sua casa. I pallini segnano le mosse legali; quando una mossa è vietata, la pagina dice perché.
40
30
  - **L'orologio**, se ne hai scelto uno, parte con **Inizia**. Anche l'AI ha il suo, e sa quanto tempo le resta.
41
31
  - **Proponi patta** nel tuo turno, dopo una mossa a testa; **Abbandona** chiude la partita.
42
- - **Gli aiuti**: con «L'AI ti insegna mentre giochi», nelle impostazioni, la scheda **Aiuti** mostra i pezzi in pericolo, le inchiodature e i pedoni, e l'AI, da allenatore, ti dà un'idea. L'AI disegna frecce colorate sulla scacchiera: il **?** accanto alle mosse spiega ogni segno.
43
32
  - **Gira** volta la scacchiera; **PGN** salva le mosse nel file che leggono tutti i siti di scacchi, da aprire su Lichess o Chess.com.
44
33
 
34
+ ## Parlare con l'AI
35
+
36
+ ![La casella per scrivere sotto il nome dell'AI, e la sua risposta](talk)
37
+
38
+ - Parli con l'AI nella **casella sotto il suo nome**, qualche parola a ogni mossa: le legge con la tua mossa. Puoi scriverle anche nella sua finestra.
39
+ - Anche una **mossa scritta** nella chat vale: `e4`, `Nf3`, con le lettere inglesi dei pezzi (K Q R B N), o a parole.
40
+ - **Il nome dell'AI** apre la scelta della chat: Claude Code o Codex, il modello (quale AI: alcune sono più veloci, altre più forti) e quanto ragiona. Più ragiona, più gioca lenta. Se cambi, la chat riparte da capo nella stessa finestra: l'AI dimentica la chiacchierata di prima, la partita resta com'è.
41
+ - A ogni **nuova partita** la chat aperta dalla pagina riparte da capo da sola, se l'AI ha finito di pensare: una chat lunga rende l'AI più lenta.
42
+
43
+ ## Gli aiuti e i segni
44
+
45
+ ![Frecce colorate e bollini sulla scacchiera, accanto alla scheda degli aiuti](helps)
46
+
47
+ - Con **«L'AI ti insegna mentre giochi»**, nelle impostazioni, la scheda **Aiuti** mostra i pezzi in pericolo, le inchiodature e i pedoni, e l'AI, da allenatore, ti dà un'idea.
48
+ - L'AI disegna **frecce colorate** sulla scacchiera: il **?** accanto alle mosse spiega ogni segno.
49
+ - Nel ripasso, un **bollino** su una mossa dice il giudizio dell'AI: un'ottima mossa, un'imprecisione, un errore grave.
50
+
45
51
  ## Il ripasso e l'analisi
46
52
 
47
- - A partita finita premi **Analizza la partita**: l'AI la ripassa e mette sulle mosse i suoi giudizi e le sue note. Le leggi scorrendo le mosse con le frecce.
53
+ ![La barra per scorrere le mosse e i giudizi sulle mosse](analysis)
54
+
55
+ - A partita finita premi **Analizza la partita**: l'AI la ripassa e mette sulle mosse i suoi giudizi e le sue note. Le leggi scorrendo le mosse con le frecce in fondo alla colonna, o cliccando una mossa.
48
56
  - **Analisi**, nell'intestazione, apre le tue analisi e carica una partita giocata altrove: incolla il suo PGN, o scegli un file .pgn.
49
57
  - Chiedi all'AI della partita nella casella sotto il suo nome.
50
58
  - **PGN annotato** salva la partita coi commenti.
51
59
 
52
60
  ## I giocatori e il profilo
53
61
 
54
- - **Chi gioca?**: la tua immagine in alto a destra sceglie un giocatore o ne aggiunge uno. Ognuno ha le sue partite e le sue impostazioni.
55
- - **Il tuo profilo**: un clic sulla tua immagine accanto alla scacchiera, o la matita in **Chi gioca?**, cambia la tua immagine, il nome, come giochi, i tuoi nomi su Lichess e Chess.com e il tuo punteggio FIDE.
62
+ ![La tua immagine in alto a destra e la finestra Chi gioca?](players)
63
+
64
+ - **Chi gioca?**: la tua immagine in alto a destra, o il tuo nome accanto alla scacchiera, apre l'elenco dei giocatori: lì ne scegli uno o ne aggiungi uno. Ognuno ha le sue partite e le sue impostazioni.
65
+ - **Il tuo profilo**: in **Chi gioca?**, la matita accanto al tuo nome cambia la tua immagine, il nome, come giochi, i tuoi nomi su Lichess e Chess.com e il tuo punteggio FIDE.
56
66
  - **Il tuo punteggio**: dai tuoi nomi lì, Chesspal legge il tuo punteggio pubblico, quello delle partite rapide se le giochi, e lo dice all'AI. Niente password: quel punteggio lo vede chiunque sul sito. Senza un nome lì, l'AI sa come giochi da **Come giochi?**
57
67
  - **Il punteggio FIDE**, se giochi tornei, lo scrivi tu: nessun sito lo dà a Chesspal. L'AI lo legge accanto a quello del sito, ognuno per sé.
58
68
  - Se carichi una partita giocata su Lichess o Chess.com, Chesspal sa da che colore giocavi tu.
59
69
 
60
70
  ## Domande e problemi
61
71
 
62
- - **L'AI è lenta**: ogni mossa la pensa davvero. Scegli un modello più veloce, o meno ragionamento, accanto ai pulsanti della chat.
72
+ - **L'AI non risponde, e il suo orologio corre**: guarda la sua finestra, che può essere finita dietro le altre: cercala nella barra in basso. Se ti sta chiedendo qualcosa, rispondi lì; se l'hai chiusa, clicca il nome dell'AI e aprine un'altra.
73
+ - **L'AI è lenta**: ogni mossa la pensa davvero. Dal suo nome scegli un modello più veloce, o meno ragionamento.
74
+ - **Un pezzo non si muove**: non è il tuo turno, o la mossa è vietata; la pagina dice perché.
75
+ - **Hai chiuso la pagina?** Riaprila dall'icona di Chesspal, sul desktop o nel menu: la partita lasciata a metà è ancora lì.
76
+ - **Le tue partite** stanno in una cartella sul tuo computer: **Chi gioca?**, dalla tua immagine in alto a destra, dice dove, e **Apri la cartella** la apre. Per tenerne una copia di sicurezza, copia la cartella, con la chat e la pagina chiuse.
77
+ - **Una versione nuova di Chesspal**: una freccia in alto te lo dice e la installa, fra una partita e l'altra.
63
78
  - **Quanto costa**: Chesspal è gratis; l'AI usa il tuo abbonamento, e non paghi niente in più.
64
79
  - **L'AI può fare una mossa illegale?** No: Chesspal controlla ogni mossa. I suoi giudizi però sono suoi, e un'AI può sbagliare, come una persona.
65
- - **Un backup**: copia la cartella delle tue partite, con la chat e la pagina chiuse.
66
80
  - **Qualcosa non va?** Raccontacelo su [GitHub](https://github.com/stefanocaronia/chesspal/issues): cosa hai fatto, cosa ti aspettavi, cosa è successo. GitHub è il sito dove si fa Chesspal: ci scrivi con un account gratuito, e chiunque può leggere.
@@ -1,4 +1,5 @@
1
1
  import { jsx as _jsx, Fragment as _Fragment, jsxs as _jsxs } from "preact/jsx-runtime";
2
+ import { drawings } from "./drawings/drawings.js";
2
3
  /** Blocks drawn as the page's elements: headings one level under the part's, each with the anchor given by its place among them; a link to an anchor calls go. */
3
4
  export function Blocks({ blocks, anchors, go }) {
4
5
  return _jsx(_Fragment, { children: blocks.map((block, index) => _jsx(BlockView, { block: block, anchors: anchors, go: go }, index)) });
@@ -47,6 +48,10 @@ function BlockView({ block, anchors, go }) {
47
48
  return (_jsx("blockquote", { children: _jsx(Blocks, { blocks: block.blocks, anchors: anchors, go: go }) }));
48
49
  case "code":
49
50
  return _jsx("pre", { children: _jsx("code", { children: block.text }) });
51
+ case "drawing": {
52
+ const Drawing = drawings[block.name];
53
+ return Drawing === undefined ? null : (_jsx("figure", { class: "guide-drawing", role: "img", "aria-label": block.alt, children: _jsx(Drawing, {}) }));
54
+ }
50
55
  case "rule":
51
56
  return null;
52
57
  }
@@ -1,4 +1,4 @@
1
- /* The helps (D-78): their signs on the board, their card, the coach and the strategy's table */
1
+ /* The helps (D-78): their signs on the board, their card, the coach and the strategy's rows */
2
2
 
3
3
  /* A piece at risk: a corner folded, bottom left, the square's free corner; in ink, or in the player's red and green (D-91) */
4
4
  .help-notch {
@@ -238,12 +238,19 @@
238
238
  padding: 3px 6px;
239
239
  }
240
240
 
241
- /* The coach's words at the top of the card (D-88): its judgment of the player's last move, then its hint, folded until they open it */
241
+ /* The coach's words at the top of the card (D-88), tinted rows as the tactics': each judgment in its badge's colour, the hint in the accent behind a bulb */
242
242
  .helps-card .coach {
243
243
  display: flex;
244
244
  flex-direction: column;
245
- gap: 6px;
246
- font-size: 14px;
245
+ gap: 3px;
246
+ font-size: 13px;
247
+ }
248
+
249
+ .helps-card .coach .judged,
250
+ .helps-card .coach .coach-hint {
251
+ --row: var(--accent);
252
+ border-radius: 6px;
253
+ background: color-mix(in srgb, var(--row) 10%, transparent);
247
254
  }
248
255
 
249
256
  .coach-hint summary {
@@ -257,6 +264,48 @@
257
264
  display: none;
258
265
  }
259
266
 
267
+ /* A row's head: its icon, its words in ink, the sign of a line that opens on the right */
268
+ .helps-card .coach .head,
269
+ .helps-card .coach summary {
270
+ display: flex;
271
+ align-items: center;
272
+ gap: 6px;
273
+ padding: 3px 8px 3px 6px;
274
+ border-radius: 6px;
275
+ color: var(--ink);
276
+ }
277
+
278
+ .helps-card .coach summary {
279
+ cursor: pointer;
280
+ list-style: none;
281
+ }
282
+
283
+ .helps-card .coach summary:hover,
284
+ .helps-card .coach details[open] > summary {
285
+ background: color-mix(in srgb, var(--row) 16%, transparent);
286
+ }
287
+
288
+ .helps-card .coach .row-icon {
289
+ display: grid;
290
+ place-items: center;
291
+ flex: none;
292
+ width: 16px;
293
+ height: 16px;
294
+ color: var(--row);
295
+ }
296
+
297
+ .board-map .coach-hint .row-icon {
298
+ display: none;
299
+ }
300
+
301
+ /* A finger needs a taller line (Zoe) */
302
+ @media (pointer: coarse) {
303
+ .helps-card .coach .head,
304
+ .helps-card .coach summary {
305
+ padding-block: 7px;
306
+ }
307
+ }
308
+
260
309
  /* The same sign on both, so that on a phone, with no pointer, they read as lines that open (Zoe) */
261
310
  .helps-card .coach summary::after,
262
311
  .board-map .coach-hint summary::after {
@@ -265,12 +314,31 @@
265
314
  color: var(--soft);
266
315
  }
267
316
 
317
+ .helps-card .coach summary::after {
318
+ margin-left: auto;
319
+ }
320
+
268
321
  .helps-card .coach details[open] > summary::after,
269
322
  .board-map .coach-hint[open] > summary::after {
270
323
  content: "▾";
271
324
  }
272
325
 
273
- .coach-hint .note {
326
+ /* The words opened, under the head's text */
327
+ .helps-card .coach .note {
328
+ display: block;
329
+ margin: 0;
330
+ padding: 2px 8px 6px 28px;
331
+ color: var(--say-ink);
332
+ font-size: 13px;
333
+ line-height: 1.4;
334
+ }
335
+
336
+ .helps-card .coach .legend {
337
+ margin: 0;
338
+ padding: 0 8px 6px 28px;
339
+ }
340
+
341
+ .board-map .coach-hint .note {
274
342
  display: block;
275
343
  margin-top: 4px;
276
344
  color: var(--say-ink);
@@ -362,17 +430,11 @@
362
430
  content: "▾";
363
431
  }
364
432
 
365
- /* A finger needs a taller line, and the whole of a strategy's name (Zoe) */
433
+ /* A finger needs a taller line (Zoe) */
366
434
  @media (pointer: coarse) {
367
435
  .help-rows .line-head {
368
436
  padding-block: 7px;
369
437
  }
370
-
371
- .strategy-table .term {
372
- display: block;
373
- width: 100%;
374
- padding: 6px 0;
375
- }
376
438
  }
377
439
 
378
440
  .help-rows .line-head:hover,
@@ -478,7 +540,8 @@
478
540
  color: var(--row);
479
541
  }
480
542
 
481
- .help-rows .row-icon svg {
543
+ .help-rows .row-icon svg,
544
+ .coach-hint .row-icon svg {
482
545
  width: 14px;
483
546
  height: 14px;
484
547
  fill: none;
@@ -552,31 +615,81 @@
552
615
  border-color: var(--accent);
553
616
  }
554
617
 
555
- .strategy-table {
556
- width: 100%;
557
- border-collapse: collapse;
558
- font-size: 12.5px;
618
+ /* The strategy (Stefano): the phases, the bar of the squares controlled, the lines in groups apart only by the gap, each a name and its tile, then the notes */
619
+ .strategy {
620
+ display: flex;
621
+ flex-direction: column;
622
+ gap: 10px;
623
+ }
624
+
625
+ /* The three phases in a row, joined by a thin line; the current one in a pill */
626
+ .phases {
627
+ display: flex;
628
+ align-items: center;
629
+ margin: 0;
630
+ padding: 0;
631
+ list-style: none;
632
+ font-size: 12px;
559
633
  color: var(--soft);
560
634
  }
561
635
 
562
- .strategy-table th,
563
- .strategy-table td {
564
- padding: 2px 4px;
565
- text-align: left;
566
- font-weight: 400;
636
+ .phases li + li {
637
+ flex: 1 1 auto;
638
+ display: flex;
639
+ align-items: center;
640
+ gap: 6px;
641
+ margin-left: 6px;
567
642
  }
568
643
 
569
- .strategy-table thead th {
644
+ .phases li + li::before {
645
+ content: "";
646
+ flex: 1;
647
+ height: 1px;
648
+ background: var(--line);
649
+ }
650
+
651
+ .phases li span {
652
+ padding: 1px 9px;
653
+ white-space: nowrap;
654
+ }
655
+
656
+ .phases li[aria-current="step"] span {
657
+ border-radius: 999px;
658
+ background: color-mix(in srgb, var(--accent) 20%, transparent);
570
659
  color: var(--ink);
571
660
  font-weight: 700;
572
661
  }
573
662
 
574
- .strategy-table tbody tr + tr {
575
- border-top: 1px solid var(--line);
663
+ /* A group of lines, 3px apart (1px of gap and the heads' 1px of padding), with no line between them */
664
+ .strategy-rows {
665
+ display: flex;
666
+ flex-direction: column;
667
+ gap: 1px;
668
+ margin: 0;
669
+ padding: 0;
670
+ list-style: none;
671
+ font-size: 12.5px;
672
+ color: var(--soft);
673
+ }
674
+
675
+ .strategy-rows .row-head {
676
+ display: grid;
677
+ grid-template-columns: minmax(0, 1fr) auto;
678
+ align-items: center;
679
+ gap: 8px;
680
+ margin: 0 -4px;
681
+ padding: 1px 4px;
682
+ border-radius: 6px;
683
+ }
684
+
685
+ /* A soft ground under the pointer and on the open line, as the tactics' lines have */
686
+ .strategy-rows .row-head:hover,
687
+ .strategy-rows li.open .row-head {
688
+ background: color-mix(in srgb, var(--soft) 12%, transparent);
576
689
  }
577
690
 
578
691
  /* A term with its meaning under the pointer, and under its line at a click or a tap (Rosa). */
579
- .strategy-table .term {
692
+ .strategy-rows .term {
580
693
  padding: 0;
581
694
  border: 0;
582
695
  background: none;
@@ -588,60 +701,32 @@
588
701
  cursor: help;
589
702
  }
590
703
 
591
- .strategy-table tbody tr.meaning {
592
- border-top: 0;
704
+ /* A finger needs the whole of a strategy's name, after the base rule so that it wins */
705
+ @media (pointer: coarse) {
706
+ .strategy-rows .term {
707
+ display: block;
708
+ width: 100%;
709
+ padding: 6px 0;
710
+ }
711
+ }
712
+
713
+ .strategy-rows li.open .term {
714
+ color: var(--ink);
593
715
  }
594
716
 
595
- .strategy-table tr.meaning td {
596
- padding-bottom: 4px;
717
+ .strategy-rows .meaning {
718
+ padding: 2px 0 4px;
597
719
  font-size: 12px;
598
720
  font-style: italic;
599
721
  }
600
722
 
601
723
  /* Under the meaning, each side's squares or files (Stefano) */
602
- .strategy-table tr.meaning .listed {
724
+ .strategy-rows .meaning .listed {
603
725
  display: block;
604
726
  margin-top: 3px;
605
727
  font-style: normal;
606
728
  }
607
729
 
608
- /* The table's groups under their figure, in the accent; the sides' heads with their pawn */
609
- .strategy-table tr.group th {
610
- padding-top: 7px;
611
- color: var(--accent);
612
- font-size: 12px;
613
- font-weight: 700;
614
- }
615
-
616
- .strategy-table tbody tr.group + tr {
617
- border-top: 0;
618
- }
619
-
620
- /* The strategy (Stefano): the phase in a pill and the open files on top, then the bar of the squares controlled, the table in groups, the notes */
621
- .strategy {
622
- display: flex;
623
- flex-direction: column;
624
- gap: 8px;
625
- }
626
-
627
- .strategy-head {
628
- display: flex;
629
- flex-wrap: wrap;
630
- align-items: center;
631
- gap: 4px 10px;
632
- margin: 0;
633
- font-size: 12px;
634
- color: var(--soft);
635
- }
636
-
637
- .strategy .phase {
638
- padding: 1px 9px;
639
- border-radius: 999px;
640
- background: color-mix(in srgb, var(--accent) 20%, transparent);
641
- color: var(--ink);
642
- font-weight: 700;
643
- }
644
-
645
730
  /* Squares and files in chips, a count in bold, a yes as a green tick, nothing as a faint dash, no more as a faint cross */
646
731
  .strategy .chip {
647
732
  display: inline-block;
@@ -689,23 +774,12 @@
689
774
  }
690
775
 
691
776
  /* The squares each side controls: White's in white, both in grey, Black's in black, each as long as its count */
692
- .control {
693
- display: grid;
694
- gap: 3px;
695
- font-size: 11px;
696
- color: var(--soft);
697
- }
698
-
699
- .control-title {
700
- font-size: 12px;
701
- }
702
-
703
777
  .control-bar {
704
778
  display: flex;
705
779
  height: 18px;
706
- border: 1px solid var(--line);
707
780
  border-radius: 5px;
708
781
  overflow: hidden;
782
+ font-size: 11px;
709
783
  font-weight: 700;
710
784
  }
711
785
 
@@ -716,28 +790,67 @@
716
790
  min-width: 20px;
717
791
  }
718
792
 
719
- .control-bar .white {
793
+ /* The thread that keeps the black half in sight on the dark theme, as the lead bar's */
794
+ .control-bar,
795
+ .row-tile {
796
+ border: 1px solid rgb(138 144 153 / 0.6);
797
+ }
798
+
799
+ /* The bar's colours, which the lines' tiles share */
800
+ .control-bar .white,
801
+ .row-tile .white {
720
802
  background: #f4f6f8;
721
803
  color: var(--fixed-ink);
722
804
  }
723
805
 
724
- .control-bar .both {
806
+ .control-bar .both,
807
+ .row-tile .both {
725
808
  background: #8d98a7;
726
- color: #fff;
809
+ color: var(--fixed-ink);
727
810
  }
728
811
 
729
- .control-bar .black {
812
+ .control-bar .black,
813
+ .row-tile .black {
730
814
  background: var(--fixed-ink);
731
815
  color: #f4f6f8;
732
816
  }
733
817
 
734
- .control-legend {
818
+ /* A line's tile: a half for each side, the player's first; the open files in one half as wide as the two */
819
+ .row-tile {
735
820
  display: flex;
736
- justify-content: space-between;
821
+ height: 20px;
822
+ border-radius: 5px;
823
+ overflow: hidden;
824
+ font-size: 12px;
825
+ font-weight: 700;
826
+ font-variant-numeric: tabular-nums;
827
+ }
828
+
829
+ .row-tile > span {
830
+ display: grid;
831
+ place-items: center;
832
+ width: 42px;
833
+ }
834
+
835
+ .row-tile > .both {
836
+ width: 84px;
737
837
  }
738
838
 
739
- .strategy-table .figurine {
740
- margin-right: 3px;
839
+ /* In a tile the marks take the half's colour, but the tick, green */
840
+ .strategy .row-tile .count {
841
+ color: inherit;
842
+ }
843
+
844
+ .strategy .row-tile .chip {
845
+ margin: 0;
846
+ padding: 0;
847
+ background: none;
848
+ color: inherit;
849
+ }
850
+
851
+ .strategy .row-tile .no svg {
852
+ stroke: currentColor;
853
+ opacity: 0.6;
741
854
  }
742
855
 
743
856
  /* On a phone, or in a narrow window, the map of the squares and the coach's hint go under the board, out of the helps' card */