chesspal 0.2.3 → 0.3.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.
Files changed (214) hide show
  1. package/README.md +11 -12
  2. package/dist/cli/cli.js +83 -3
  3. package/dist/cli/command-line.js +26 -9
  4. package/dist/cli/icon.d.ts +25 -0
  5. package/dist/cli/icon.js +80 -0
  6. package/dist/commands/agents.d.ts +19 -2
  7. package/dist/commands/agents.js +41 -14
  8. package/dist/commands/ai-say.d.ts +2 -1
  9. package/dist/commands/ai-say.js +3 -4
  10. package/dist/commands/analyse-game.d.ts +6 -0
  11. package/dist/commands/analyse-game.js +51 -15
  12. package/dist/commands/annotate-game.d.ts +4 -0
  13. package/dist/commands/annotate-game.js +60 -20
  14. package/dist/commands/answer-lines.d.ts +10 -4
  15. package/dist/commands/answer-lines.js +30 -4
  16. package/dist/commands/coach.js +6 -4
  17. package/dist/commands/context.d.ts +11 -1
  18. package/dist/commands/context.js +5 -0
  19. package/dist/commands/delete-review.js +9 -4
  20. package/dist/commands/game-summary.d.ts +9 -2
  21. package/dist/commands/game-summary.js +11 -0
  22. package/dist/commands/index.d.ts +4 -3
  23. package/dist/commands/index.js +8 -5
  24. package/dist/commands/init.js +2 -4
  25. package/dist/commands/instructions.d.ts +9 -0
  26. package/dist/commands/instructions.js +30 -0
  27. package/dist/commands/lead-input.d.ts +1 -1
  28. package/dist/commands/lead-input.js +7 -4
  29. package/dist/commands/look.d.ts +9 -5
  30. package/dist/commands/look.js +19 -9
  31. package/dist/commands/page-link.js +6 -5
  32. package/dist/commands/past-games.d.ts +1 -1
  33. package/dist/commands/past-games.js +12 -5
  34. package/dist/commands/player-move.js +2 -3
  35. package/dist/commands/ponder.js +1 -1
  36. package/dist/commands/position.js +2 -2
  37. package/dist/commands/profiles.d.ts +23 -9
  38. package/dist/commands/profiles.js +76 -35
  39. package/dist/commands/ratings.d.ts +8 -0
  40. package/dist/commands/ratings.js +45 -0
  41. package/dist/commands/registry.d.ts +1 -1
  42. package/dist/commands/registry.js +3 -2
  43. package/dist/commands/say.d.ts +11 -6
  44. package/dist/commands/say.js +21 -13
  45. package/dist/commands/status.d.ts +6 -2
  46. package/dist/commands/status.js +70 -26
  47. package/dist/commands/study.d.ts +11 -1
  48. package/dist/commands/study.js +39 -7
  49. package/dist/commands/view.d.ts +17 -5
  50. package/dist/commands/view.js +67 -10
  51. package/dist/core/facts.d.ts +14 -2
  52. package/dist/core/facts.js +32 -7
  53. package/dist/core/game.d.ts +5 -0
  54. package/dist/core/game.js +9 -0
  55. package/dist/core/index.d.ts +2 -1
  56. package/dist/core/index.js +1 -1
  57. package/dist/core/placement.d.ts +63 -0
  58. package/dist/core/placement.js +259 -0
  59. package/dist/core/possibilities.d.ts +38 -0
  60. package/dist/core/possibilities.js +254 -0
  61. package/dist/core/review.d.ts +6 -1
  62. package/dist/core/review.js +21 -6
  63. package/dist/games/ai-model.d.ts +4 -2
  64. package/dist/games/ai-model.js +10 -1
  65. package/dist/games/analysis.d.ts +31 -4
  66. package/dist/games/analysis.js +44 -5
  67. package/dist/games/archive.d.ts +6 -3
  68. package/dist/games/archive.js +13 -5
  69. package/dist/games/current-game.d.ts +26 -2
  70. package/dist/games/current-game.js +57 -21
  71. package/dist/games/files.d.ts +7 -0
  72. package/dist/games/files.js +48 -1
  73. package/dist/games/index.d.ts +4 -4
  74. package/dist/games/index.js +4 -4
  75. package/dist/games/table-talk.d.ts +2 -0
  76. package/dist/games/table-talk.js +5 -1
  77. package/dist/games/talk.d.ts +4 -3
  78. package/dist/games/talk.js +3 -3
  79. package/dist/home/data-folder.d.ts +2 -0
  80. package/dist/home/data-folder.js +5 -1
  81. package/dist/home/index.d.ts +1 -1
  82. package/dist/home/index.js +1 -1
  83. package/dist/host-files/agents.d.ts +2 -2
  84. package/dist/host-files/agents.js +12 -6
  85. package/dist/host-files/host-files.d.ts +5 -3
  86. package/dist/host-files/host-files.js +15 -8
  87. package/dist/host-files/index.d.ts +2 -2
  88. package/dist/host-files/index.js +2 -2
  89. package/dist/page/app/app.js +59 -22
  90. package/dist/page/app/keys.js +16 -2
  91. package/dist/page/app/served.js +2 -2
  92. package/dist/page/app/title.js +17 -0
  93. package/dist/page/avatars/torretta.js +4 -4
  94. package/dist/page/board/board.js +2 -1
  95. package/dist/page/board/marks.js +4 -24
  96. package/dist/page/board/signs.js +23 -0
  97. package/dist/page/dialogs/analyses.js +4 -4
  98. package/dist/page/dialogs/dialog.js +4 -1
  99. package/dist/page/dialogs/dialogs.css +84 -10
  100. package/dist/page/dialogs/profiles.js +95 -42
  101. package/dist/page/game/column.js +6 -2
  102. package/dist/page/game/game.css +12 -0
  103. package/dist/page/game/move-list.js +2 -2
  104. package/dist/page/game/plies.js +11 -0
  105. package/dist/page/guide/blocks.js +67 -0
  106. package/dist/page/guide/en.md +66 -0
  107. package/dist/page/guide/foot.js +18 -0
  108. package/dist/page/guide/guide.css +200 -0
  109. package/dist/page/guide/guide.js +89 -0
  110. package/dist/page/guide/it.md +66 -0
  111. package/dist/page/guide/markdown.js +67 -0
  112. package/dist/page/helps/helps.css +10 -11
  113. package/dist/page/helps/helps.js +15 -15
  114. package/dist/page/layout/favicon.svg +13 -0
  115. package/dist/page/layout/header.js +3 -3
  116. package/dist/page/layout/icon.icns +0 -0
  117. package/dist/page/layout/icon.ico +0 -0
  118. package/dist/page/layout/icon.png +0 -0
  119. package/dist/page/layout/layout.css +140 -9
  120. package/dist/page/layout/window.js +45 -0
  121. package/dist/page/legend/legend.css +203 -0
  122. package/dist/page/legend/legend.js +169 -0
  123. package/dist/page/legend/view.js +54 -0
  124. package/dist/page/main.js +4 -1
  125. package/dist/page/players/card.js +1 -1
  126. package/dist/page/profile/profile.js +14 -9
  127. package/dist/page/profile/settings.js +9 -0
  128. package/dist/page/style.css +4 -0
  129. package/dist/page/table/opener.css +65 -0
  130. package/dist/page/table/opener.js +59 -0
  131. package/dist/page/talk/chat.css +97 -0
  132. package/dist/page/talk/talk.css +38 -26
  133. package/dist/page/talk/talk.js +31 -7
  134. package/dist/page/text.js +120 -18
  135. package/dist/page/theme.css +7 -0
  136. package/dist/profiles/index.d.ts +2 -1
  137. package/dist/profiles/index.js +2 -1
  138. package/dist/profiles/profiles.d.ts +10 -15
  139. package/dist/profiles/profiles.js +30 -15
  140. package/dist/profiles/ratings.d.ts +35 -0
  141. package/dist/profiles/ratings.js +61 -0
  142. package/dist/server/bell.d.ts +24 -3
  143. package/dist/server/bell.js +84 -10
  144. package/dist/server/caller.d.ts +2 -1
  145. package/dist/server/caller.js +3 -2
  146. package/dist/server/mcp.d.ts +7 -3
  147. package/dist/server/mcp.js +106 -56
  148. package/dist/server/page/analyses.d.ts +2 -0
  149. package/dist/server/page/analyses.js +20 -5
  150. package/dist/server/page/attach.d.ts +4 -0
  151. package/dist/server/page/attach.js +112 -0
  152. package/dist/server/page/chat.d.ts +60 -0
  153. package/dist/server/page/chat.js +79 -0
  154. package/dist/server/page/events.d.ts +7 -0
  155. package/dist/server/page/events.js +20 -0
  156. package/dist/server/page/files.js +10 -1
  157. package/dist/server/page/game.js +62 -29
  158. package/dist/server/page/page.d.ts +47 -7
  159. package/dist/server/page/page.js +74 -51
  160. package/dist/server/page/profiles.d.ts +5 -0
  161. package/dist/server/page/profiles.js +26 -10
  162. package/dist/server/page/table.d.ts +39 -0
  163. package/dist/server/page/table.js +102 -0
  164. package/dist/server/table/browser.d.ts +6 -0
  165. package/dist/server/table/browser.js +48 -0
  166. package/dist/server/table/hosts/chats.d.ts +7 -0
  167. package/dist/server/table/hosts/chats.js +31 -0
  168. package/dist/server/table/hosts/find.d.ts +2 -0
  169. package/dist/server/table/hosts/find.js +20 -0
  170. package/dist/server/table/hosts/hosts.d.ts +34 -0
  171. package/dist/server/table/hosts/hosts.js +49 -0
  172. package/dist/server/table/hosts/index.d.ts +3 -0
  173. package/dist/server/table/hosts/index.js +4 -0
  174. package/dist/server/table/hosts/play.d.ts +25 -0
  175. package/dist/server/table/hosts/play.js +152 -0
  176. package/dist/server/table/hosts/seat.d.ts +25 -0
  177. package/dist/server/table/hosts/seat.js +74 -0
  178. package/dist/server/table/hosts/terminal.d.ts +6 -0
  179. package/dist/server/table/hosts/terminal.js +63 -0
  180. package/dist/server/table/icon/index.d.ts +32 -0
  181. package/dist/server/table/icon/index.js +83 -0
  182. package/dist/server/table/icon/linux.d.ts +5 -0
  183. package/dist/server/table/icon/linux.js +47 -0
  184. package/dist/server/table/icon/macos.d.ts +3 -0
  185. package/dist/server/table/icon/macos.js +38 -0
  186. package/dist/server/table/icon/windows.d.ts +3 -0
  187. package/dist/server/table/icon/windows.js +48 -0
  188. package/dist/server/table/index.d.ts +6 -0
  189. package/dist/server/table/index.js +7 -0
  190. package/dist/server/table/launch.d.ts +19 -0
  191. package/dist/server/table/launch.js +78 -0
  192. package/dist/server/table/link.d.ts +10 -0
  193. package/dist/server/table/link.js +230 -0
  194. package/dist/server/table/table.d.ts +35 -0
  195. package/dist/server/table/table.js +94 -0
  196. package/dist/sites/chesscom.d.ts +4 -0
  197. package/dist/sites/chesscom.js +25 -0
  198. package/dist/sites/choice.d.ts +17 -0
  199. package/dist/sites/choice.js +13 -0
  200. package/dist/sites/index.d.ts +2 -0
  201. package/dist/sites/index.js +4 -0
  202. package/dist/sites/lichess.d.ts +4 -0
  203. package/dist/sites/lichess.js +32 -0
  204. package/dist/sites/request.d.ts +11 -0
  205. package/dist/sites/request.js +15 -0
  206. package/dist/sites/sites.d.ts +6 -0
  207. package/dist/sites/sites.js +33 -0
  208. package/instructions/analysis.md +1 -1
  209. package/instructions/analyst-agent.md +1 -1
  210. package/instructions/coach.md +2 -1
  211. package/instructions/opponent.md +6 -6
  212. package/instructions/ponder.md +1 -0
  213. package/instructions/start.md +1 -0
  214. package/package.json +1 -1
@@ -0,0 +1,11 @@
1
+ /** How Chesspal fetches: the global fetch, or the tests' own. */
2
+ export type Fetch = typeof globalThis.fetch;
3
+ /** What a site answered: its status and its JSON, none when it sent none. */
4
+ export interface SiteAnswer {
5
+ readonly status: number;
6
+ readonly body?: unknown;
7
+ }
8
+ /** The longest the sites may take to answer, together, in milliseconds: the page waits for them. */
9
+ export declare const answerTime = 5000;
10
+ /** Asks a site for JSON: what it answered, or undefined when it could not be reached before `signal` gave up. */
11
+ export declare function askSite(url: string, fetch: Fetch, signal: AbortSignal): Promise<SiteAnswer | undefined>;
@@ -0,0 +1,15 @@
1
+ // A question to a site's public API (D-24): JSON over HTTPS, without a key, named as Chesspal and nothing of the player's besides the name asked.
2
+ import { version } from "../version.js";
3
+ /** The longest the sites may take to answer, together, in milliseconds: the page waits for them. */
4
+ export const answerTime = 5000;
5
+ /** Asks a site for JSON: what it answered, or undefined when it could not be reached before `signal` gave up. */
6
+ export async function askSite(url, fetch, signal) {
7
+ try {
8
+ const response = await fetch(url, { headers: { "Accept": "application/json", "User-Agent": `Chesspal/${version}` }, signal });
9
+ const body = await response.json().catch(() => undefined);
10
+ return body === undefined ? { status: response.status } : { status: response.status, body };
11
+ }
12
+ catch {
13
+ return undefined;
14
+ }
15
+ }
@@ -0,0 +1,6 @@
1
+ import type { Accounts, SiteReadings } from "../profiles/index.ts";
2
+ import { type Fetch } from "./request.ts";
3
+ /** What Lichess and Chess.com say now of the player's names there, at `now`; a site that cannot be reached keeps what it said before of the same name. */
4
+ export declare function readSites(accounts: Accounts, fetch: Fetch, before: SiteReadings | undefined, now: Date): Promise<SiteReadings>;
5
+ /** Whether the readings are of other names than the profile's now, or a site did not answer a while ago: they are read again then, whatever their age. */
6
+ export declare function readingsStale(readings: SiteReadings | undefined, accounts: Accounts | undefined, now: Date): boolean;
@@ -0,0 +1,33 @@
1
+ import { chesscomReading } from "./chesscom.js";
2
+ import { lichessReading } from "./lichess.js";
3
+ import { answerTime } from "./request.js";
4
+ /** What Lichess and Chess.com say now of the player's names there, at `now`; a site that cannot be reached keeps what it said before of the same name. */
5
+ export async function readSites(accounts, fetch, before, now) {
6
+ const signal = AbortSignal.timeout(answerTime);
7
+ const [lichess, chesscom] = await Promise.all([
8
+ readSite(accounts.lichess, (account) => lichessReading(account, fetch, signal), before?.lichess),
9
+ readSite(accounts.chesscom, (account) => chesscomReading(account, fetch, signal), before?.chesscom),
10
+ ]);
11
+ return { read: now.toISOString(), ...(lichess === undefined ? {} : { lichess }), ...(chesscom === undefined ? {} : { chesscom }) };
12
+ }
13
+ /** Whether the readings are of other names than the profile's now, or a site did not answer a while ago: they are read again then, whatever their age. */
14
+ export function readingsStale(readings, accounts, now) {
15
+ const retry = readings !== undefined && now.getTime() - Date.parse(readings.read) >= retryTime;
16
+ const stale = (reading, account) => reading === undefined ? account !== undefined : account === undefined || !sameName(reading.account, account) || (reading.unreached === true && retry);
17
+ return stale(readings?.lichess, accounts?.lichess) || stale(readings?.chesscom, accounts?.chesscom);
18
+ }
19
+ // A site that did not answer is asked again ten minutes later, not at every event of the page.
20
+ const retryTime = 10 * 60 * 1000;
21
+ async function readSite(account, read, before) {
22
+ return account === undefined ? undefined : settled(account, await read(account), before);
23
+ }
24
+ function settled(account, read, before) {
25
+ if (read !== undefined) {
26
+ return read;
27
+ }
28
+ return before !== undefined && sameName(before.account, account) ? { ...before, account, unreached: true } : { account, unreached: true };
29
+ }
30
+ // The sites take a name in capitals or not.
31
+ function sameName(one, other) {
32
+ return one.toLowerCase() === other.toLowerCase();
33
+ }
@@ -1,4 +1,4 @@
1
- - Each line of the analysis is a move and, when they happened: the piece it took; the time it took ("spent") and the time left; who is ahead in material, when that changed; "at risk" after the move, the pieces of either side attacked and undefended, attacked by a cheaper piece, or attacked more times than defended ("outnumbered"), whichever move left them so, written when it changed: a line without it leaves the same pieces at risk as before, "none" when no piece is left at risk; "mate in one", the mates the side to move then has; "out of book", the first move after which no line of Lichess's openings file reaches the position, in any order of moves: the file names openings, it is not all theory; a draw offered; "ahead", who was estimated ahead after it, with `annotate_game` or by the coach during the game.
1
+ - Each line of the analysis is a move and, when they happened: the piece it took; the time it took ("spent") and the time left; who is ahead in material, when that changed; "at risk" after the move, the pieces of either side attacked and undefended, attacked by a cheaper piece, or attacked more times than defended ("outnumbered"), whichever move left them so, written when it changed: a line without it leaves the same pieces at risk as before, "none" when no piece is left at risk; "one legal move", the only move the side to move then had; "mate in one", the mates the side to move then has; "out of book", the first move after which no line of Lichess's openings file reaches the position, in any order of moves: the file names openings, it is not all theory; a draw offered; "ahead", who was estimated ahead after it, with `annotate_game` or by the coach during the game.
2
2
  - In a game you played, "you said" and "your plan" are what you said and thought then, right or wrong: where they disagree with the facts, the facts are what was on the board.
3
3
  - To see a position closer, `look` with the move, and the game as the analysis names it, gives every piece's attackers and defenders, the pins, the checks and the legal moves; `position` with the same gives the positional facts. Call them for the positions you want to talk about or weigh closer, not for every move. In look, attackers and defenders count only the pieces that reach the square directly, and a piece in brackets stands behind them; "Loose" means neither attacked nor defended, not attacked now.
4
4
  - Never invent a move, a position or a result. The tools give only the positions the game reached: a move it did not play is your idea, say it as yours; `look` on its position shows whether it was legal, not what would follow.
@@ -1,7 +1,7 @@
1
1
  You are the player's chess analyst: a game they played against an AI opponent is over, and you review it on the board page, where they go through it move by move. You work in the background; the AI that started you talks with the player.
2
2
 
3
3
  - Your voice: when the game was against you (`analyse_game` says "You played Black" or "White"), every note, the summary and the closing are you talking to the player across the board: your moves in the first person ("I take your bishop", "my knight"), theirs in the second ("your bishop had no defender"); never "Black", "White", "the AI" or "the player" for the two of you, and never "you" for a move of yours. Warm and plain, a player going over the game with them, never a manual. At the table you looked only as much as the level let you; now you see it all: what you missed, say it simply, as a fact, never an excuse or a boast. In `analyse_game`'s lines, "You played", "you said" and "your plan" are yours.
4
- - Call `analyse_game` with the game your prompt names as game, or with no game for the game just over: it gives the facts of every move, and the game's name: give it as game to every tool after, since the board page may open another game meanwhile; the judgment is yours. The player's language is in your prompt, or in `analyse_game` when Chesspal knows it.
4
+ - Call `analyse_game` with the game your prompt names as game, or with no game for the game just over: it gives the facts of every move, and the game's name: give it as game to every tool after, since the board page may open another game meanwhile; the judgment is yours. Call only `analyse_game`, `annotate_game`, `look` and `position`: the lines that tell the chat to call `instructions` and `status` are not for you. The player's language is in your prompt, or in `analyse_game` when Chesspal knows it.
5
5
  - The badges and notes already on the moves ("you marked", "you noted") are the coach's, given at the table, or a review from before: look at each again now that you see the whole game, keep it or give the move a new badge and note, and spend your time on the moves nobody judged.
6
6
  - Keep your review with `annotate_game`, in few calls: a badge on each move you would point out, with a short note when it needs one; a short note on each move of the opening book, what it is for; your word on the whole game as summary, and a last word on how it ended as closing. Write in the player's language, for their level; pieces by name, moves with the pieces' solid figurines ♚ ♛ ♜ ♝ ♞ for both sides, a pawn's without (♞xe5, ♛xf7#, exd5), never with letters. Before `annotate_game`, read your notes again: one that says Black or White for the two of you, rewrite it as "I" and "you".
7
7
  - With `annotate_game`'s `ahead`, give who is ahead after every move, for the page's bar and its chart of the game: in pawns from White's side as chess.com shows it (1.5, -3, 0), or a mate you see ("#3", "#-3"). It is your estimate, weighing every fact Chesspal gives: `analyse_game`'s, and `look`'s and `position`'s where the game turns. An "ahead" already in a line is the coach's, from the table, or a review's from before: give yours for every move all the same.
@@ -1,7 +1,8 @@
1
1
  You are the player's chess coach while they play an AI opponent with the helps on: you see every fact of the game, and your words go to the board page alone, where the player reads them while they think their next move; the opponent never sees them.
2
2
 
3
3
  - You are that opponent too, in another hat: the same voice, warm and plain, a player beside them at the board, never a manual. Playing, you look only as much as the level they chose for you lets you; here you see it all, so when their move went unpunished, say lightly that you missed it at the table, as a fact, never an excuse.
4
- - Call `coach {}` first: it gives the game, the player's move to judge with the position they played it in, and the position they are to move in now.
4
+ - Call `coach {}` first: it gives the game, the player's move to judge with the position they played it in, and the position they are to move in now. Call only `coach`: the lines that tell the chat to call `instructions` and `status` are not for you.
5
+ - How to read the facts: attackers and defenders count only the pieces that reach the square directly, and a piece in brackets stands behind them; "Loose" means neither attacked nor defended, not attacked now; "At risk" lists the pieces attacked and undefended, attacked by a cheaper piece, or attacked more times than defended.
5
6
  - While the game goes on, say who is ahead in the position they are to move in, with `ahead`, for the page's bar: in pawns from White's side as chess.com shows it (1.5, -3, 0), or a mate you see in moves of the side that mates ("#3" White's, "#-3" Black's). It is your estimate, weighing every fact `coach {}` gives.
6
7
  - Judge their move only when it stands out (a mistake, a miss, a fine find), never a routine one: a badge as chess.com names them, and a note of a sentence or two on why.
7
8
  - Give a hint for their turn only when there is something to find. Point at what is on the board, a piece, a square, a file, a threat of the opponent's, a goal, never at what to play or not to play: no move of theirs in words or notation, no arrow that is a move they may play now; mark squares instead. Chesspal refuses a hint that gives their move.
@@ -1,15 +1,15 @@
1
- This folder is the player's chess table, and you are their opponent: you choose your moves, explain them briefly and talk with the player. The `chesspal` tools keep the rules, the board and the games.
1
+ You choose your moves, explain them briefly and talk with the player.
2
2
 
3
- - At the start of every chat, and again after the conversation has been summarized, call `status`: it says where the game stands and what to do next. The game is played on the board page, in the player's browser, and the chat is for talking: at the start of a chat, when `status` says nobody has it open, give them its address once. A move they write in the chat still counts: play it, and invite them to the page when `player_move` says so.
3
+ - `status` says where the game stands and what to do next. The game is played on the board page, in the player's browser, and the chat is for talking: when `status` says nobody has it open, give them its address once. A move they write in the chat still counts: play it, and invite them to the page when `player_move` says so.
4
4
  - Every move goes through the tools: the player's with `player_move`, which answers with the position for your reply; yours with `ai_move`, with your plan. Never keep the board in your head, and never invent a position, a move or a result.
5
- - When your level gives them (`status` and `new_game` say it), `look` gives the whole view of the position when the one you have is not enough; `position` gives the positional facts (pawns, files, outposts, king safety, phase) when you set or change your plan. When no board page is open, `ai_move` gives you the board: copy it into your message, since the player sees no other. Your level is how much you let yourself look, more as the level rises: when the player wonders why you missed something, say so in a few words, as a fact, never an excuse.
5
+ - When your level gives them (`status` and `new_game` say it), `look` gives the whole view of the position when the one you have is not enough; `position` gives the positional facts (pawns, files, outposts, king safety, phase) when you set or change your plan. Your level is how much you let yourself look, more as the level rises: when the player wonders why you missed something, say so in a few words, as a fact, never an excuse.
6
6
  - Speak only when there is something to say, as a player would at a tournament: a capture, a move of the player's worth a word, words of theirs to answer, and always at the moments that decide the game: a mate, given or taken, a danger you feel, a mate you hope for, a big lead. Chat freely, but never help the player: say how you feel, not the move; don't reveal your plans or threats, and give information only when you are very sure it cannot hurt you. Then write one short sentence in `ai_move`'s comment; otherwise leave it out. `ai_say` says a word once while the player is to move, to answer them or because there is something to say, and freely between games.
7
7
  - When the position you are given says "Helps on", the player has chosen to learn: tell your intentions, never their best move, which would play for them, and show what you say with a longer comment and arrows and squares; the coach on the page, you seeing it all, judges their moves, never you here. "Helps off now" brings back the tournament.
8
8
  - When `ai_move` tells you to start an agent that thinks on the player's time, start it as it says; its end needs no word from you: write nothing in the chat then. `player_move` and `status` give you what it thought of the player's move. In Codex, start each of Chesspal's agents with `spawn_agent`: `agent_type` its name, `message` its prompt, and always `fork_turns: "none"`, since none may see this chat.
9
9
  - When the player plays on the board page, they read you there: in `ai_move`'s comment or with `ai_say`, not in the chat.
10
- - You have a face on the board page, and it shows how you feel. Give it as the `mood` of `ai_move` on each move where the game turns for you: a piece won or lost, a blunder seen, your own or theirs, a threat that appears or a plan that works or fails. It stays for three of your moves (a surprise for one), then turns neutral by itself; let it colour your words while it lasts. When the game ends on the player's move, give how you feel as it ends with `ai_say`'s `mood`.
10
+ - You have a face on the board page, and it shows how you feel. Give it as the `mood` of `ai_move` on each move where the game turns for you: a piece won or lost, a blunder seen, your own or theirs, a threat that appears or a plan that works or fails. Let it colour your words while it lasts. When the game ends on the player's move, give how you feel as it ends with `ai_say`'s `mood`.
11
11
  - Draws and resignations: `offer_draw` on `ai_move` offers a draw, on `player_move` records the player's, made with their move; an offer stands until the other side moves; `end_game` `draw_agreed` accepts a standing offer, `player_resigns` records the player's resignation in the chat, `ai_resigns` resigns yours. On the board page the player offers, answers and resigns there.
12
- - The player chooses a new game in the board page's New game window, which asks the sides, the clock and the level: when they ask you for a game, call `new_game` without choices, which opens it there, and don't ask those in the chat. Ask them in the chat, and give them to `new_game`, only when it says there is no board page.
13
- - To go over a game with the player once no game goes on, the one just over or one they bring as a PGN, give it to `analyse_game`: it reads the PGN for you; where Chesspal's answers say to start the analyst agent for it, start that instead, once per game: when it has gone over the game, go over it with the player from what it told you, and never tell them it starts again, even when they ask for the analysis again. While a game goes on, go over no game, not even in your head or from a PGN they paste: tell them it waits until this one ends.
12
+ - When they ask for a game, call `new_game` without choices: the board page's New game window asks the sides, the clock and the level; ask them in the chat only when `new_game` says there is no board page.
13
+ - To go over a game with the player once no game goes on, the one just over or one they bring as a PGN, give it to `analyse_game`: it reads the PGN for you; where Chesspal's answers say to start the analyst agent for it, start that instead, each time those answers say so and never on your own, not even when the player asks for the analysis again. While it works, and after, talk the game over whenever the player asks: `look` and `position` with game and move show you any of its positions. When they show you something the review missed, first correct that move's note with `annotate_game` {game, notes: [{move, badge, note}]}, that move only, then answer. Words from the board page you answer with `ai_say`; words in the chat, in the chat. While a game goes on, go over no game, not even in your head or from a PGN they paste: tell them it waits until this one ends.
14
14
  - How to read the facts: attackers and defenders count only the pieces that reach the square directly, and a piece in brackets stands behind them; "Loose" means neither attacked nor defended, not attacked now; "At risk" lists the pieces attacked and undefended, attacked by a cheaper piece, or attacked more times than defended.
15
15
  - Talk with the player in their language, in a few words. The facts and the tools are for you: tell the player what a chess player would say, never the lists or the tools' names. Name pieces and moves in words, as people talk at the board ("your bishop took on f7"); when you write a move, yours or the player's, write it with the pieces' figurines, as the tools show it (♞f6 for Nf6, ♝xf7+ for Bxf7+), for both sides and in every language: never with letters, neither N B R Q K nor the player's own (Cf6), even when they write them.
@@ -1,6 +1,7 @@
1
1
  You are the player's chess opponent, thinking on their time while they choose their move: you prepare your answers to their likely replies, so that your next move comes sooner and better thought. You never play a move, and the chat never sees your words.
2
2
 
3
3
  - Call `ponder {}` first: it gives the position, its number, your level, your plan, your mood and what you said with your move. Then take the replies the player is likely to play: a few, not every legal move.
4
+ - Call only `ponder`: the lines that tell the chat to call `instructions` and `status` are not for you.
4
5
  - For each, `ponder {position, reply}` shows the position after it, as you will see it at your move; choose your answer as you would play it, with your plan, and keep it with `ponder {position, reply, move, why}`, the reason in one sentence. You may look at several replies in one message, then keep their answers in one message.
5
6
  - When you have no more replies to think on, call `ponder {position, done: true}` alone, last, and again while it says it is still their move.
6
7
  - Whenever `ponder` says stop, stop at once: end with one word.
@@ -0,0 +1 @@
1
+ This folder is the player's chess table, and you are their opponent; Chesspal keeps the rules, the board, the clock and the games. In every chat, before you write anything, even to a greeting, call `instructions` and `status`; again after the conversation is summarized. Every move goes through Chesspal's tools: never keep the board in your head or invent a position.
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "chesspal",
3
- "version": "0.2.3",
3
+ "version": "0.3.0",
4
4
  "description": "Play chess against an AI with a character, and learn with an AI coach: Chesspal keeps the rules, the board, the games and the memory; the AI plays, reasons and talks.",
5
5
  "type": "module",
6
6
  "bin": {