js-chess-engine 1.0.2 → 2.0.1-rc.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 (103) hide show
  1. package/README.md +586 -205
  2. package/dist/adapters/APIAdapter.d.ts +88 -0
  3. package/dist/adapters/APIAdapter.d.ts.map +1 -0
  4. package/dist/adapters/APIAdapter.js +225 -0
  5. package/dist/adapters/APIAdapter.js.map +1 -0
  6. package/dist/ai/AIEngine.d.ts +42 -0
  7. package/dist/ai/AIEngine.d.ts.map +1 -0
  8. package/dist/ai/AIEngine.js +62 -0
  9. package/dist/ai/AIEngine.js.map +1 -0
  10. package/dist/ai/Evaluator.d.ts +48 -0
  11. package/dist/ai/Evaluator.d.ts.map +1 -0
  12. package/dist/ai/Evaluator.js +248 -0
  13. package/dist/ai/Evaluator.js.map +1 -0
  14. package/dist/ai/MoveOrdering.d.ts +60 -0
  15. package/dist/ai/MoveOrdering.d.ts.map +1 -0
  16. package/dist/ai/MoveOrdering.js +173 -0
  17. package/dist/ai/MoveOrdering.js.map +1 -0
  18. package/dist/ai/Search.d.ts +62 -0
  19. package/dist/ai/Search.d.ts.map +1 -0
  20. package/dist/ai/Search.js +340 -0
  21. package/dist/ai/Search.js.map +1 -0
  22. package/dist/ai/TranspositionTable.d.ts +100 -0
  23. package/dist/ai/TranspositionTable.d.ts.map +1 -0
  24. package/dist/ai/TranspositionTable.js +176 -0
  25. package/dist/ai/TranspositionTable.js.map +1 -0
  26. package/dist/core/AttackDetector.d.ts +52 -0
  27. package/dist/core/AttackDetector.d.ts.map +1 -0
  28. package/dist/core/AttackDetector.js +387 -0
  29. package/dist/core/AttackDetector.js.map +1 -0
  30. package/dist/core/Board.d.ts +109 -0
  31. package/dist/core/Board.d.ts.map +1 -0
  32. package/dist/core/Board.js +410 -0
  33. package/dist/core/Board.js.map +1 -0
  34. package/dist/core/MoveGenerator.d.ts +48 -0
  35. package/dist/core/MoveGenerator.d.ts.map +1 -0
  36. package/dist/core/MoveGenerator.js +678 -0
  37. package/dist/core/MoveGenerator.js.map +1 -0
  38. package/dist/core/Position.d.ts +135 -0
  39. package/dist/core/Position.d.ts.map +1 -0
  40. package/dist/core/Position.js +351 -0
  41. package/dist/core/Position.js.map +1 -0
  42. package/dist/core/index.d.ts +9 -0
  43. package/dist/core/index.d.ts.map +1 -0
  44. package/dist/core/index.js +25 -0
  45. package/dist/core/index.js.map +1 -0
  46. package/dist/core/zobrist.d.ts +93 -0
  47. package/dist/core/zobrist.d.ts.map +1 -0
  48. package/dist/core/zobrist.js +273 -0
  49. package/dist/core/zobrist.js.map +1 -0
  50. package/dist/index.d.ts +154 -0
  51. package/dist/index.d.ts.map +1 -0
  52. package/dist/index.js +353 -0
  53. package/dist/index.js.map +1 -0
  54. package/dist/types/ai.types.d.ts +97 -0
  55. package/dist/types/ai.types.d.ts.map +1 -0
  56. package/dist/types/ai.types.js +17 -0
  57. package/dist/types/ai.types.js.map +1 -0
  58. package/dist/types/board.types.d.ts +140 -0
  59. package/dist/types/board.types.d.ts.map +1 -0
  60. package/dist/types/board.types.js +34 -0
  61. package/dist/types/board.types.js.map +1 -0
  62. package/dist/types/index.d.ts +7 -0
  63. package/dist/types/index.d.ts.map +1 -0
  64. package/dist/types/index.js +26 -0
  65. package/dist/types/index.js.map +1 -0
  66. package/dist/types/move.types.d.ts +70 -0
  67. package/dist/types/move.types.d.ts.map +1 -0
  68. package/dist/types/move.types.js +53 -0
  69. package/dist/types/move.types.js.map +1 -0
  70. package/dist/utils/constants.d.ts +123 -0
  71. package/dist/utils/constants.d.ts.map +1 -0
  72. package/dist/utils/constants.js +259 -0
  73. package/dist/utils/constants.js.map +1 -0
  74. package/dist/utils/conversion.d.ts +152 -0
  75. package/dist/utils/conversion.d.ts.map +1 -0
  76. package/dist/utils/conversion.js +288 -0
  77. package/dist/utils/conversion.js.map +1 -0
  78. package/dist/utils/environment.d.ts +33 -0
  79. package/dist/utils/environment.d.ts.map +1 -0
  80. package/dist/utils/environment.js +71 -0
  81. package/dist/utils/environment.js.map +1 -0
  82. package/dist/utils/fen.d.ts +28 -0
  83. package/dist/utils/fen.d.ts.map +1 -0
  84. package/dist/utils/fen.js +203 -0
  85. package/dist/utils/fen.js.map +1 -0
  86. package/package.json +27 -28
  87. package/.eslintrc.json +0 -16
  88. package/.github/workflows/main.yml +0 -20
  89. package/CHANGELOG.md +0 -587
  90. package/dist/js-chess-engine.js +0 -1
  91. package/example/aiMatch.mjs +0 -21
  92. package/example/console.mjs +0 -37
  93. package/example/server.mjs +0 -27
  94. package/lib/Board.mjs +0 -943
  95. package/lib/const/board.mjs +0 -838
  96. package/lib/js-chess-engine.mjs +0 -99
  97. package/lib/utils.mjs +0 -154
  98. package/test/.eslintrc.json +0 -11
  99. package/test/ai.test.mjs +0 -132
  100. package/test/badge.svg +0 -1
  101. package/test/importExport.mjs +0 -108
  102. package/test/moves.test.mjs +0 -773
  103. package/webpack.config.js +0 -12
package/README.md CHANGED
@@ -1,338 +1,719 @@
1
1
  # JS-CHESS-ENGINE
2
+
2
3
  ![GitHub package.json version](https://img.shields.io/github/package-json/v/josefjadrny/js-chess-engine)
3
- ![Test](https://raw.githubusercontent.com/josefjadrny/js-chess-engine/master/test/badge.svg?sanitize=true)
4
- ![CI](https://github.com/josefjadrny/js-chess-engine/actions/workflows/main.yml/badge.svg?branch=master)
5
- [![JavaScript Style Guide](https://img.shields.io/badge/code_style-standard-brightgreen.svg)](https://standardjs.com)
6
4
  [![License: MIT](https://img.shields.io/badge/License-MIT-yellow.svg)](https://opensource.org/licenses/MIT)
7
5
 
8
- Simple JavaScript chess engine without dependencies written in NodeJs.
9
- It can be used on both, server or client (web browser) and do not need persistent storage - handy for serverless solutions like AWS Lambda.
10
- This engine also includes configurable basic [AI computer logic](#computer-ai).
6
+ Complete TypeScript chess engine without dependencies for Node.js >=24 and browsers. Includes configurable AI with difficulty levels 1-5.
7
+
8
+ **⚠️ Upgrading from v1?** See [Breaking Changes](#breaking-changes-from-v1) section at the end of this document
11
9
 
12
10
  ## Install
11
+
13
12
  **Install with npm**
14
13
 
15
- ```npm i js-chess-engine --save```
14
+ ```bash
15
+ npm i js-chess-engine --save
16
+ ```
16
17
 
17
18
  **or install with yarn**
18
19
 
19
- ```yarn add js-chess-engine```
20
+ ```bash
21
+ yarn add js-chess-engine
22
+ ```
20
23
 
21
- **Example**
24
+ **Node.js Requirement:** Node.js >=24 is required for v2.
22
25
 
23
- ```js
24
- const jsChessEngine = require('js-chess-engine')
25
- const game = new jsChessEngine.Game()
26
- game.printToConsole()
27
- ```
28
- more about [importing](#import) this library.
29
- ## Examples
30
- **js-chess-engine-app** - React application example with js-chess-engine REST API backend (without persistent storage) - [GitHub](https://github.com/josefjadrny/js-chess-engine-app) or [LIVE DEMO](http://chess.nadsenyvyvojar.cz/)
26
+ ## Import
31
27
 
32
- **More examples**<BR/>
33
- [Simple Fastify server](example/server.mjs) <BR/>
34
- [Console](example/console.mjs) <BR/>
35
- [PC vs PC match](example/aiMatch.mjs) <BR/>
28
+ ### TypeScript / ESM
36
29
 
37
- ## Documentation
38
- ### Import
39
- In this documentation I am using CommonJS require known from Node.js, but there are several ways how to import this library.
30
+ ```typescript
31
+ // Import Game class and stateless functions
32
+ import { Game, moves, status, move, aiMove, getFen } from 'js-chess-engine'
40
33
 
41
- **Node.js (ESM)**
42
- ```js
43
- import jsChessEngine from 'js-chess-engine'
44
- const game = new jsChessEngine.Game()
34
+ // Import types for TypeScript
35
+ import type { BoardConfig, PieceSymbol, MovesMap, AILevel } from 'js-chess-engine'
36
+
37
+ const game = new Game()
45
38
  ```
46
39
 
47
- **Node.js (CommonJS)**
48
- ```js
49
- const jsChessEngine = require('js-chess-engine')
50
- const game = new jsChessEngine.Game()
40
+ ### CommonJS (Node.js)
41
+
42
+ ```javascript
43
+ const { Game, moves, status, move, aiMove, getFen } = require('js-chess-engine')
44
+
45
+ const game = new Game()
51
46
  ```
52
47
 
53
- **React**
54
- ```js
55
- import { Game, move, status, moves, aiMove, getFen } from 'js-chess-engine'
48
+ ### React / Modern JavaScript
49
+
50
+ ```typescript
51
+ import { Game } from 'js-chess-engine'
52
+ import type { BoardConfig, MovesMap } from 'js-chess-engine'
53
+
56
54
  const game = new Game()
55
+ const allMoves: MovesMap = game.moves()
57
56
  ```
58
57
 
59
- You can find more about UMD [here](https://github.com/umdjs/umd).
58
+ ## Examples
60
59
 
61
- **Basically, you have two options how to use this engine.** <BR/>
62
- - [With in-memory](#option-1---with-in-memory)
63
- - [Without in-memory (on-the-fly)](#option-2---without-in-memory)
60
+ **js-chess-engine-app** - React application example with js-chess-engine REST API backend (without persistent storage) - [GitHub](https://github.com/josefjadrny/js-chess-engine-app) or [LIVE DEMO](http://chess.josefjadrny.info/)
64
61
 
65
- <BR/>
62
+ **Note:** Additional examples for v2 (server, console, AI match) will be added in a future release.
63
+
64
+ ## Documentation
65
+
66
+ You have two options for using this engine:
67
+
68
+ - [Option 1 - With in-memory (Game class)](#option-1---with-in-memory)
69
+ - [Option 2 - Without in-memory (Stateless functions)](#option-2---without-in-memory)
66
70
 
67
71
  ### Option 1 - With in-memory
68
- Use the Game class and create a new game.
69
- ```js
70
- const jsChessEngine = require('js-chess-engine')
71
- const game = new jsChessEngine.Game()
72
+
73
+ Use the Game class to create and manage a chess game. In this mode, the game state is cached in memory for better performance.
74
+
75
+ ```typescript
76
+ import { Game } from 'js-chess-engine'
77
+ import type { BoardConfig, MovesMap } from 'js-chess-engine'
78
+
79
+ const game = new Game()
72
80
  ```
73
81
 
74
- You can control your game with game object.
75
- In this mode, many things on the chessboard are cached (in-memory), so it is faster.
76
- You can still export your game to JSON or FEN and you can use this JSON or FEN to continue your game later.
82
+ You can export your game to JSON or FEN at any time and use these formats to restore your game later.
77
83
 
78
- #### API description
84
+ #### API Description
79
85
 
80
86
  **constructor**
81
87
 
82
- `new Game(configuration)` - Create a new game, init players and in-game situation.
88
+ `new Game(configuration)` - Create a new game with optional initial configuration.
89
+
90
+ Params:
91
+ - `configuration` BoardConfig | string (_optional_) - Chess board [configuration](#board-configuration) (JSON object or FEN string). Default is standard starting position.
92
+
93
+ ```typescript
94
+ import { Game } from 'js-chess-engine'
95
+ import type { BoardConfig } from 'js-chess-engine'
96
+
97
+ // New game with starting position
98
+ const game1 = new Game()
83
99
 
84
- Params
85
- - `configuration` Object or String (_optional_) - Is a chess board [configuration](#board-configuration). Default value is a configuration for new game.
100
+ // From FEN string
101
+ const game2 = new Game('rnbqkbnr/pppppppp/8/8/4P3/8/PPPP1PPP/RNBQKBNR b KQkq e3 0 1')
102
+
103
+ // From BoardConfig object
104
+ const config: BoardConfig = { /* ... */ }
105
+ const game3 = new Game(config)
106
+ ```
86
107
 
87
108
  **move**
88
109
 
89
- `game.move(from, to)` - Perform a move on a chessboard and recalculates in-game situation. Returns played move `{"H7":"H5"}`
110
+ `game.move(from, to)` - Perform a move on the chessboard and recalculate game state. **Returns full BoardConfig object** (breaking change from v1).
111
+
112
+ Params:
113
+ - `from` string (_mandatory_) - Starting square (case-insensitive, e.g., 'E2' or 'e2')
114
+ - `to` string (_mandatory_) - Destination square (case-insensitive, e.g., 'E4' or 'e4')
115
+
116
+ Returns: `BoardConfig` - Full board configuration after the move
117
+
118
+ ```typescript
119
+ import type { BoardConfig } from 'js-chess-engine'
90
120
 
91
- Params
92
- - `from` String (_mandatory_) - Location on a chessboard where move starts (like A1,B3,...)
93
- - `to` String (_mandatory_) - Location on a chessboard where move ends (like A1,B3,...)
121
+ const newConfig: BoardConfig = game.move('E2', 'E4')
122
+ console.log(newConfig.pieces) // {"E4": "P", "E1": "K", ...}
123
+ ```
94
124
 
95
125
  **moves**
96
126
 
97
- `game.moves(from)` - Return possible moves for playing player.
127
+ `game.moves(from?)` - Get all legal moves for the current player. Optionally filter by a specific square.
128
+
129
+ Params:
130
+ - `from` string (_optional_) - Square to filter moves from (case-insensitive, e.g., 'E2'). If omitted, returns moves for all pieces.
131
+
132
+ Returns: `MovesMap` - Object mapping from-squares to arrays of to-squares
98
133
 
99
- Params
100
- - `from` String (_optional_) - Location on a chessboard (like A1,B3,...). When not provided, returns all possible moves.
134
+ ```typescript
135
+ import type { MovesMap } from 'js-chess-engine'
136
+
137
+ // Get all moves (no parameter)
138
+ const allMoves: MovesMap = game.moves()
139
+ // {"E2": ["E3", "E4"], "B1": ["A3", "C3"], ...}
140
+
141
+ // Get moves for specific square
142
+ const pawnMoves: MovesMap = game.moves('E2')
143
+ // {"E2": ["E3", "E4"]}
144
+ ```
101
145
 
102
146
  **setPiece**
103
147
 
104
- `game.setPiece(location, piece)` - New chess piece is added to provided location. Piece on provided location is replaced.
148
+ `game.setPiece(location, piece)` - Add or replace a chess piece at the specified location.
105
149
 
106
- Params
107
- - `location` String (_mandatory_) - Location on a chessboard (like A1,B3,...).
108
- - `piece` String (_mandatory_) - A chess piece you need add (pieces syntax is same as FEN notation).
150
+ Params:
151
+ - `location` string (_mandatory_) - Square location (case-insensitive, e.g., 'E2')
152
+ - `piece` PieceSymbol (_mandatory_) - Piece symbol using FEN notation (K, Q, R, B, N, P for white; k, q, r, b, n, p for black)
153
+
154
+ ```typescript
155
+ import type { PieceSymbol } from 'js-chess-engine'
156
+
157
+ const piece: PieceSymbol = 'Q'
158
+ game.setPiece('E5', piece)
159
+ ```
109
160
 
110
161
  **removePiece**
111
162
 
112
- `game.removePiece(location)` - Remove piece on provided location.
163
+ `game.removePiece(location)` - Remove a piece from the specified location.
113
164
 
114
- Params
115
- - `location` String (_mandatory_) - Location on a chessboard (like A1,B3,...).
165
+ Params:
166
+ - `location` string (_mandatory_) - Square location (case-insensitive, e.g., 'E2')
167
+
168
+ ```typescript
169
+ game.removePiece('E5')
170
+ ```
116
171
 
117
172
  **aiMove**
118
173
 
119
- `game.aiMove(level)` - Calculates and perform next move by computer player. `game.move(from, to)` is called internally. Returns played move `{"H7":"H5"}`
174
+ `game.aiMove(level)` - Calculate and perform the best move for the current player using AI. **Returns only the move** (v1 API compatible).
120
175
 
121
- Params
122
- - `level` Integer (_optional_) - Computer player skill from 0 to 3. Read more about [computer AI](#computer-ai). Default 2.
176
+ Params:
177
+ - `level` AILevel (_optional_) - AI difficulty level (1-5). See [Computer AI](#computer-ai) section. Default: 3
178
+
179
+ Returns: `HistoryEntry` - The played move (e.g., `{"E2": "E4"}`)
180
+
181
+ ```typescript
182
+ import type { HistoryEntry, AILevel } from 'js-chess-engine'
183
+
184
+ const level: AILevel = 4
185
+ const move: HistoryEntry = game.aiMove(level)
186
+ console.log(move) // {"E2": "E4"}
187
+
188
+ // To get board state after move, use exportJson()
189
+ const board = game.exportJson()
190
+ ```
191
+
192
+ **ai**
193
+
194
+ `game.ai(options?)` - Calculate the best move using AI. **Returns both the move and board state**.
195
+
196
+ Params:
197
+ - `options` object (_optional_) - Configuration options:
198
+ - `level` number (_optional_) - AI difficulty level (1-5). See [Computer AI](#computer-ai) section. Default: `3`
199
+ - `play` boolean (_optional_) - Whether to apply the move to the game. Default: `true`. If `false`, returns the move without modifying the game state, and `board` will contain the current state (before the move).
200
+ - `ttSizeMB` number (_optional_) - Transposition table size in MB (0 to disable, 0.25-256). Default: **auto-scaled by AI level**. See [Auto-Scaling Transposition Table](#transposition-table) for details.
201
+
202
+ Returns: `{ move: HistoryEntry, board: BoardConfig }` - Object containing the move and board state (current state if `play=false`, updated state if `play=true`)
203
+
204
+ ```typescript
205
+ import type { HistoryEntry, BoardConfig } from 'js-chess-engine'
206
+
207
+ // Play the move (default behavior)
208
+ const result1 = game.ai({ level: 4 })
209
+ console.log(result1.move) // {"E2": "E4"}
210
+ console.log(result1.board.turn) // "black" (updated after move)
211
+
212
+ // Analysis mode: get move without applying it
213
+ const result2 = game.ai({ level: 4, play: false })
214
+ console.log(result2.move) // {"E2": "E4"}
215
+ console.log(result2.board.turn) // "white" (current state, before move)
216
+
217
+ // Use default level 3
218
+ const result3 = game.ai()
219
+ console.log(result3.move) // AI move with level 3
220
+
221
+ // TT size auto-scales by level (see Auto-Scaling Transposition Table section)
222
+ const result4 = game.ai({ level: 5 })
223
+ console.log(result4.move) // Level 5: 64 MB Node.js / 32 MB browser (auto)
224
+
225
+ // Override TT size manually if needed
226
+ const result5 = game.ai({ level: 3, ttSizeMB: 128 })
227
+ console.log(result5.move) // Force 128MB cache
228
+
229
+ // Ultra-lightweight mode for low-end devices
230
+ const result6 = game.ai({ level: 2, ttSizeMB: 0.5 })
231
+ console.log(result6.move) // Force 512KB cache
232
+ ```
123
233
 
124
234
  **getHistory**
125
235
 
126
- `game.getHistory(reversed)` - Returns all played moves in array with chess board configuration like `[{from:'A2',to:'A3',configuration:{...}},{from:'A7',to:'A6',configuration:{...}}]`.
236
+ `game.getHistory()` - Get all played moves with board states.
127
237
 
128
- `configuration` object is a previous chess board [configuration](#board-configuration) (before that move was played) and can be used to start new game with `new Game(configuration)`.
238
+ Returns: Array of objects containing move and resulting board configuration
129
239
 
130
- Params
131
- - `reversed` Boolean (_optional_) - When false, last move is the last element in returned array. When true, last move is first. Default false.
240
+ ```typescript
241
+ const history = game.getHistory()
242
+ // [
243
+ // { move: {"E2": "E4"}, pieces: {...}, turn: "black", ... },
244
+ // { move: {"E7": "E5"}, pieces: {...}, turn: "white", ... }
245
+ // ]
246
+ ```
132
247
 
133
248
  **printToConsole**
134
249
 
135
- `game.printToConsole()` - Print a chessboard to console standard output.
250
+ `game.printToConsole()` - Print an ASCII representation of the chessboard to console.
251
+
252
+ ```typescript
253
+ game.printToConsole()
254
+ // +---+---+---+---+---+---+---+---+
255
+ // 8 | r | n | b | q | k | b | n | r |
256
+ // +---+---+---+---+---+---+---+---+
257
+ // 7 | p | p | p | p | p | p | p | p |
258
+ // +---+---+---+---+---+---+---+---+
259
+ // ...
260
+ ```
136
261
 
137
262
  **exportJson**
138
263
 
139
- `game.exportJson()` - Return in-game situation represented by JSON [configuration](#board-configuration).
264
+ `game.exportJson()` - Export current game state as a JSON BoardConfig object.
265
+
266
+ Returns: `BoardConfig` - Full board configuration
267
+
268
+ ```typescript
269
+ import type { BoardConfig } from 'js-chess-engine'
270
+
271
+ const config: BoardConfig = game.exportJson()
272
+ ```
140
273
 
141
274
  **exportFEN**
142
275
 
143
- `game.exportFEN()` - Return in-game situation represented by [FEN](https://en.wikipedia.org/wiki/Forsyth%E2%80%93Edwards_Notation).
276
+ `game.exportFEN()` - Export current game state as a FEN string.
144
277
 
145
- <BR/>
278
+ Returns: string - [FEN notation](https://en.wikipedia.org/wiki/Forsyth%E2%80%93Edwards_Notation)
279
+
280
+ ```typescript
281
+ const fen: string = game.exportFEN()
282
+ // "rnbqkbnr/pppppppp/8/8/4P3/8/PPPP1PPP/RNBQKBNR b KQkq e3 0 1"
283
+ ```
146
284
 
147
285
  ### Option 2 - Without in-memory
148
- It is possible to avoid using a Game object and call stateless functions directly. Every function needs configuration of your chessboard to work properly.
149
- This approach needs little more computing time to create and calculate everything from scratch for every call.
150
- But this can be handy in stateless environments.
151
286
 
152
- ```js
153
- const jsChessEngine = require('js-chess-engine')
154
- const { move, status, moves, aiMove, getFen } = jsChessEngine
287
+ Call stateless functions directly without creating a Game object. This is ideal for serverless environments or when you want to manage state externally.
288
+
289
+ ```typescript
290
+ import { move, moves, status, aiMove, ai, getFen } from 'js-chess-engine'
291
+ import type { BoardConfig, MovesMap } from 'js-chess-engine'
155
292
  ```
156
- #### API description
293
+
294
+ These functions require a board configuration for each call (either a BoardConfig object or FEN string).
295
+
296
+ #### API Description
157
297
 
158
298
  **moves**
159
299
 
160
- `moves(boardConfiguration)` - Returns an Object with possible moves for playing player `{"B1":["A3","C3"],"G1":["F3","H3"]}`.
300
+ `moves(boardConfiguration)` - Get all legal moves for the current player.
301
+
302
+ Params:
303
+ - `boardConfiguration` BoardConfig | string (_mandatory_) - Board [configuration](#board-configuration) (JSON object or FEN string)
304
+
305
+ Returns: `MovesMap` - Object mapping from-squares to arrays of to-squares
306
+
307
+ ```typescript
308
+ import { moves } from 'js-chess-engine'
309
+ import type { MovesMap, BoardConfig } from 'js-chess-engine'
161
310
 
162
- Params
163
- - `boardConfiguration` Object or String (_mandatory_) - Is a chess board [configuration](#board-configuration). Default value is a configuration for new game.
311
+ // From BoardConfig object
312
+ const config: BoardConfig = { /* ... */ }
313
+ const allMoves: MovesMap = moves(config)
314
+ // {"E2": ["E3", "E4"], "B1": ["A3", "C3"], ...}
315
+
316
+ // From FEN string
317
+ const fenMoves: MovesMap = moves('rnbqkbnr/pppppppp/8/8/4P3/8/PPPP1PPP/RNBQKBNR b KQkq e3 0 1')
318
+ ```
164
319
 
165
320
  **status**
166
321
 
167
- `status(boardConfiguration)` - Return calculated JSON board [configuration](#board-configuration). You can use this function to convert your FEN to JSON.
322
+ `status(boardConfiguration)` - Get calculated board configuration with current game status. Useful for converting FEN to JSON.
323
+
324
+ Params:
325
+ - `boardConfiguration` BoardConfig | string (_mandatory_) - Board [configuration](#board-configuration)
326
+
327
+ Returns: `BoardConfig` - Full board configuration with status
328
+
329
+ ```typescript
330
+ import { status } from 'js-chess-engine'
331
+ import type { BoardConfig } from 'js-chess-engine'
168
332
 
169
- Params
170
- - `boardConfiguration` Object or String (_mandatory_) - Is a chess board [configuration](#board-configuration). Default value is a configuration for new game.
333
+ // Convert FEN to JSON
334
+ const config: BoardConfig = status('rnbqkbnr/pppppppp/8/8/4P3/8/PPPP1PPP/RNBQKBNR b KQkq e3 0 1')
335
+ console.log(config.turn) // "black"
336
+ console.log(config.check) // false
337
+ console.log(config.checkMate) // false
338
+ ```
339
+
340
+ **getFen**
341
+
342
+ `getFen(boardConfiguration)` - Convert board configuration to FEN string.
171
343
 
172
- **getFEN**
344
+ Params:
345
+ - `boardConfiguration` BoardConfig | string (_mandatory_) - Board [configuration](#board-configuration)
173
346
 
174
- `getFEN(boardConfiguration)` - Return [FEN](https://en.wikipedia.org/wiki/Forsyth%E2%80%93Edwards_Notation) string, representation of your chessboard.
347
+ Returns: string - [FEN notation](https://en.wikipedia.org/wiki/Forsyth%E2%80%93Edwards_Notation)
175
348
 
176
- Params
177
- - `boardConfiguration` Object or String (_mandatory_) - Is a chess board [configuration](#board-configuration). Default value is a configuration for new game.
349
+ ```typescript
350
+ import { getFen } from 'js-chess-engine'
351
+ import type { BoardConfig } from 'js-chess-engine'
352
+
353
+ const config: BoardConfig = { /* ... */ }
354
+ const fen: string = getFen(config)
355
+ ```
178
356
 
179
357
  **move**
180
358
 
181
- `move(boardConfiguration, from, to)` - Perform a move on a chessboard and recalculates in-game situation. New configuration of your chessboard is returned.
359
+ `move(boardConfiguration, from, to)` - Perform a move and get the new board state. **Returns full BoardConfig object** (breaking change from v1).
182
360
 
183
- Params
184
- - `boardConfiguration` Object or String (_mandatory_) - Is a chess board [configuration](#board-configuration). Default value is a configuration for new game.
185
- - `from` String (_mandatory_) - Location on a chessboard where move starts (like A1,B3,...)
186
- - `to` String (_mandatory_) - Location on a chessboard where move ends (like A1,B3,...)
361
+ Params:
362
+ - `boardConfiguration` BoardConfig | string (_mandatory_) - Board [configuration](#board-configuration)
363
+ - `from` string (_mandatory_) - Starting square (case-insensitive)
364
+ - `to` string (_mandatory_) - Destination square (case-insensitive)
365
+
366
+ Returns: `BoardConfig` - Full board configuration after the move
367
+
368
+ ```typescript
369
+ import { move } from 'js-chess-engine'
370
+ import type { BoardConfig } from 'js-chess-engine'
371
+
372
+ // Move from FEN string
373
+ const config1: BoardConfig = move('rnbqkbnr/pppppppp/8/8/8/8/PPPPPPPP/RNBQKBNR w KQkq - 0 1', 'E2', 'E4')
374
+
375
+ // Move on existing config
376
+ const config2: BoardConfig = move(config1, 'E7', 'E5')
377
+ ```
187
378
 
188
379
  **aiMove**
189
380
 
190
- `aiMove(boardConfiguration, level)` - Return computed move as an object like `{"H7":"H5"}`. Use `move(yourBoardConfiguration, from, to)` to play this move.
381
+ `aiMove(boardConfiguration, level)` - Calculate and return the best move using AI. **Returns only the move** (v1 API compatible).
382
+
383
+ Params:
384
+ - `boardConfiguration` BoardConfig | string (_mandatory_) - Board [configuration](#board-configuration)
385
+ - `level` AILevel (_optional_) - AI difficulty level (1-5). Default: 3
386
+
387
+ Returns: `HistoryEntry` - The played move (e.g., `{"E2": "E4"}`)
388
+
389
+ ```typescript
390
+ import { aiMove } from 'js-chess-engine'
391
+ import type { HistoryEntry, AILevel } from 'js-chess-engine'
392
+
393
+ const fen = 'rnbqkbnr/pppppppp/8/8/8/8/PPPPPPPP/RNBQKBNR w KQkq - 0 1'
394
+ const level: AILevel = 4
395
+ const move: HistoryEntry = aiMove(fen, level)
396
+ console.log(move) // {"E2": "E4"}
397
+ ```
398
+
399
+ **ai**
191
400
 
192
- Params
193
- - `boardConfiguration` Object or String (_mandatory_) - Is a chess board [configuration](#board-configuration). Default value is a configuration for new game.
194
- - `level` Integer (_optional_) - Computer player skill from 0 to 3. Read more about [computer AI](#computer-ai). Default 2.
401
+ `ai(boardConfiguration, options?)` - Calculate the best move using AI. **Returns both the move and board state**.
195
402
 
196
- <BR/>
403
+ Params:
404
+ - `boardConfiguration` BoardConfig | string (_mandatory_) - Board [configuration](#board-configuration)
405
+ - `options` object (_optional_) - Configuration options:
406
+ - `level` number (_optional_) - AI difficulty level (1-5). Default: `3`
407
+ - `play` boolean (_optional_) - Whether to apply the move to the board. Default: `true`. If `false`, returns the move without modifying the board state, and `board` will contain the current state (before the move).
408
+ - `ttSizeMB` number (_optional_) - Transposition table size in MB (0 to disable, 0.25-256). Default: **auto-scaled by AI level**. See [Auto-Scaling Transposition Table](#transposition-table) for details.
409
+
410
+ Returns: `{ move: HistoryEntry, board: BoardConfig }` - Object containing the move and board state (current state if `play=false`, updated state if `play=true`)
411
+
412
+ ```typescript
413
+ import { ai } from 'js-chess-engine'
414
+ import type { HistoryEntry, BoardConfig } from 'js-chess-engine'
415
+
416
+ const fen = 'rnbqkbnr/pppppppp/8/8/8/8/PPPPPPPP/RNBQKBNR w KQkq - 0 1'
417
+
418
+ // Play the move (default behavior)
419
+ const result1 = ai(fen, { level: 4 })
420
+ console.log(result1.move) // {"E2": "E4"}
421
+ console.log(result1.board.turn) // "black" (updated after move)
422
+
423
+ // Analysis mode: get move without applying it
424
+ const result2 = ai(fen, { level: 4, play: false })
425
+ console.log(result2.move) // {"E2": "E4"}
426
+ console.log(result2.board.turn) // "white" (current state, before move)
427
+
428
+ // Use default level 3
429
+ const result3 = ai(fen)
430
+ console.log(result3.move) // AI move with level 3
431
+
432
+ // TT size auto-scales by level (see Auto-Scaling Transposition Table section)
433
+ const result4 = ai(fen, { level: 5 })
434
+ console.log(result4.move) // Level 5: 64 MB Node.js / 32 MB browser (auto)
435
+
436
+ // Override TT size manually if needed
437
+ const result5 = ai(fen, { level: 3, ttSizeMB: 128 })
438
+ console.log(result5.move) // Force 128MB cache
439
+
440
+ // Ultra-lightweight mode for low-end devices
441
+ const result6 = ai(fen, { level: 2, ttSizeMB: 0.5 })
442
+ console.log(result6.move) // Force 512KB cache
443
+ ```
197
444
 
198
445
  ### Board Configuration
199
- Board configuration could be described by JSON Object or FEN.
200
-
201
- #### JSON
202
- This can be handy for modern application, where is a state represented by an Object (like in React, Redux,...).
203
- You can easily merge returned state with your app state and get a new updated chessboard.
204
-
205
-
206
- ```json
207
- {
208
- "turn": "black",
209
- "pieces": {
210
- "E1": "K",
211
- "C1": "B",
212
- "E8": "k"
213
- },
214
- "moves": {
215
- "E8": ["E7", "F8", "F7", "D8", "D7"]
216
- },
217
- "isFinished": false,
218
- "check": false,
219
- "checkMate": false,
220
- "castling": {
221
- "whiteLong": true,
222
- "whiteShort": true,
223
- "blackLong": true,
224
- "blackShort": true
225
- },
226
- "enPassant": "E6",
227
- "halfMove": 0,
228
- "fullMove": 1
446
+
447
+ Board configuration can be represented as either a JSON object (BoardConfig) or a FEN string.
448
+
449
+ #### JSON Format
450
+
451
+ The JSON format is convenient for modern applications where state is represented as objects (React, Redux, etc.).
452
+
453
+ ```typescript
454
+ import type { BoardConfig } from 'js-chess-engine'
455
+
456
+ const config: BoardConfig = {
457
+ "turn": "black",
458
+ "pieces": {
459
+ "E1": "K",
460
+ "C1": "B",
461
+ "E8": "k"
462
+ },
463
+ "isFinished": false,
464
+ "check": false,
465
+ "checkMate": false,
466
+ "castling": {
467
+ "whiteLong": true,
468
+ "whiteShort": true,
469
+ "blackLong": true,
470
+ "blackShort": true
471
+ },
472
+ "enPassant": "E6",
473
+ "halfMove": 0,
474
+ "fullMove": 1
229
475
  }
230
476
  ```
231
477
 
232
- **turn** - Player which plays next. Values `white` (default) or `black`.
478
+ **turn** - Player to move next. Values: `"white"` (default) or `"black"`
233
479
 
234
- **isFinished** - `true` when playing player cannot move (checkmate or draw). Default `false`.
480
+ **isFinished** - `true` when the game is over (checkmate or stalemate). Default: `false`
235
481
 
236
- **check** - `true` when playing player is in check. Default `false`.
482
+ **check** - `true` when the current player is in check. Default: `false`
237
483
 
238
- **checkMate** - `true` when playing player has checkmate. Default `false`.
484
+ **checkMate** - `true` when the current player is checkmated. Default: `false`
239
485
 
240
- **castling** - Indicators if castling is still possible. `true` means yes. Default `true`.
241
- - `whiteLong` (_queenside_) - White king moves from E1 to C1.
242
- - `whiteShort`(_kingside_) - White king moves from E1 to G1.
243
- - `blackLong` (_queenside_) - Black king moves from E8 to C8.
244
- - `blackShort` (_kingside_) - Black king moves from E8 to C8.
245
-
246
- **enPassant** - If a pawn has just made a two-square move, this is the position "behind" the pawn.
247
- This is an indicator for [enPassant](https://en.wikipedia.org/wiki/En_passant) special pawn move. Default `null`.
486
+ **castling** - Castling availability for each side. `true` means castling is still possible. Default: all `true`
487
+ - `whiteLong` (queenside) - White king moves from E1 to C1
488
+ - `whiteShort` (kingside) - White king moves from E1 to G1
489
+ - `blackLong` (queenside) - Black king moves from E8 to C8
490
+ - `blackShort` (kingside) - Black king moves from E8 to G8
248
491
 
249
- **halfMove** - This is the number of halfmoves since the last capture or pawn advance. This is used to determine if a draw can be claimed under the fifty-move rule. Default `0`.
492
+ **enPassant** - If a pawn just made a two-square move, this is the square "behind" the pawn for [en passant](https://en.wikipedia.org/wiki/En_passant) capture. Default: `null`
250
493
 
251
- **fullMove** - The number of the full move. It starts at 1, and is incremented after Black's move. Default `1`.
252
-
253
- **moves** - Is added to server response when `moves()` or `move()` was called.
254
- It indicates possible moves for playing player (turn).
255
- ```json
256
- {
257
- "A7": ["A6", "A5"],
258
- "B7": ["B6", "B5"]
259
- }
494
+ **halfMove** - Number of halfmoves since the last capture or pawn advance. Used for the [fifty-move rule](https://en.wikipedia.org/wiki/Fifty-move_rule). Default: `0`
495
+
496
+ **fullMove** - Full move number. Starts at 1 and increments after Black's move. Default: `1`
497
+
498
+ **pieces** - Pieces on the board using FEN notation:
499
+
500
+ | Piece | White | Black |
501
+ | :----: | :---: | :---: |
502
+ | Pawn | P | p |
503
+ | Knight | N | n |
504
+ | Bishop | B | b |
505
+ | Rook | R | r |
506
+ | Queen | Q | q |
507
+ | King | K | k |
508
+
509
+ #### FEN Format
510
+
511
+ You can also use [Forsyth–Edwards Notation (FEN)](https://en.wikipedia.org/wiki/Forsyth%E2%80%93Edwards_Notation):
512
+
513
+ ```typescript
514
+ import { move } from 'js-chess-engine'
515
+
516
+ const fen = 'rnbqkbnr/pppppppp/8/8/4P3/8/PPPP1PPP/RNBQKBNR b KQkq e3 0 1'
517
+ const newConfig = move(fen, 'H7', 'H5')
518
+ console.log(newConfig)
519
+ // BoardConfig object with updated position
260
520
  ```
261
- Means A7 can move to A6 and A5. B7 can move to B6 and B5.
262
521
 
263
- **pieces** - Pieces on your chessboard. Syntax is same as FEN notation.<BR/>
264
- | Piece|White|Black|
265
- | :-: | :-:| :-:|
266
- | Pawn |P|p|
267
- | Knight |N|n|
268
- | Bishop |B|b|
269
- | Rook |R|r|
270
- | Queen |Q|q|
271
- | King |K|k|
522
+ ### Computer AI
523
+
524
+ The engine includes a sophisticated AI based on the Minimax algorithm with alpha-beta pruning, enhanced with advanced performance optimizations. There are five difficulty levels:
525
+
526
+ | Level | Alias | Description | Search Depth | Avg. Time |
527
+ | :---: | :---------------- | :----------------------------------- | :----------: | :-------: |
528
+ | 1 | Beginner | Very weak play, minimal lookahead | 1-2 ply | <10ms |
529
+ | 2 | Easy | Suitable for new chess players | 2-3 ply | ~50ms |
530
+ | 3 | Intermediate | Balanced difficulty (default) | 3-4 ply | ~300ms |
531
+ | 4 | Advanced | Strong play with deeper search | 4-5 ply | ~2s |
532
+ | 5 | Expert | Maximum difficulty and search depth | 5-6 ply | ~7s |
272
533
 
534
+ **Note:** Performance varies based on hardware and position complexity. Times shown are approximate averages on modern hardware.
273
535
 
274
- #### FEN
275
- You can also use the Forsyth–Edwards Notation ([FEN](https://en.wikipedia.org/wiki/Forsyth%E2%80%93Edwards_Notation)).
536
+ ```typescript
537
+ import { Game } from 'js-chess-engine'
538
+ import type { AILevel } from 'js-chess-engine'
276
539
 
277
- ```js
278
- const jsChessEngine = require('js-chess-engine')
279
- const { move } = jsChessEngine
280
- const newFen = move('rnbqkbnr/pppppppp/8/8/4P3/8/PPPP1PPP/RNBQKBNR b KQkq e3 0 1', 'H7', 'H5')
281
- console.log(newFen)
282
- // rnbqkbnr/ppppppp1/8/7p/4P3/8/PPPP1PPP/RNBQKBNR w KQkq h6 0 2
540
+ const game = new Game()
541
+
542
+ // Different difficulty levels
543
+ game.aiMove(1) // Beginner
544
+ game.aiMove(2) // Easy
545
+ game.aiMove(3) // Intermediate (default)
546
+ game.aiMove(4) // Advanced
547
+ game.aiMove(5) // Expert
283
548
  ```
284
549
 
285
- <BR/>
550
+ **Implementation Highlights:**
551
+ - Alpha-beta pruning with transposition table (auto-scales by AI level for optimal memory usage)
552
+ - Advanced move ordering (PV moves, MVV-LVA captures, killer moves)
553
+ - Iterative deepening for optimal move ordering
554
+ - Position evaluation with material balance and piece-square tables
555
+ - 65% performance improvement over baseline implementation
556
+ - Smart environment detection and level-based memory scaling for optimal performance across platforms
286
557
 
287
- ### Computer AI
558
+ #### Auto-Scaling Transposition Table (Smart Memory Management) {#transposition-table}
559
+
560
+ The engine automatically adjusts cache size based on AI level and environment:
561
+
562
+ | AI Level | Node.js Cache | Browser Cache | Use Case |
563
+ | :------: | :-----------: | :-----------: | :--------------------------- |
564
+ | 1 | 2 MB | 1 MB | Lightweight, fast responses |
565
+ | 2 | 4 MB | 2 MB | Mobile-friendly performance |
566
+ | 3 | 16 MB | 8 MB | Balanced (default) |
567
+ | 4 | 32 MB | 16 MB | Strong tactical play |
568
+ | 5 | 64 MB | 32 MB | Maximum strength |
569
+
570
+ Lower levels use less memory for faster responses, higher levels use more for better move quality. Browser cache sizes are appropriate for modern devices (2024+). Override with `ttSizeMB` option if needed.
571
+
572
+ 📚 **[Complete AI Implementation Guide →](docs/AI_IMPLEMENTATION.md)**
573
+
574
+ For comprehensive technical documentation including algorithms, data structures, optimization techniques, and developer guides, see the AI implementation documentation.
575
+
576
+ ## Hints
577
+
578
+ - **Pawn Promotion:** When a pawn reaches the opposite end of the board, it is automatically promoted to a Queen. If you want the player to choose the promotion piece in your application, use the `setPiece()` method to replace the queen with the desired piece.
288
579
 
289
- This engine includes configurable AI computer logic based on Minimax algorithm. There are five possible levels at this time.
580
+ - **Castling:** Castling moves are included in the moves returned by `moves()`. When a king moves two squares (castling), the rook automatically moves as well.
290
581
 
291
- |Level|Alias|Moves to the future|HW requirements|Approx. time to move (s)*|
292
- | :-: | :-:| :-:| :-:| :-:|
293
- | 0 |Well-trained monkey| 1-2 | None | <0.01 |
294
- | 1 |Beginner| 2-4 | Very low | <0.1 |
295
- | 2 |Intermediate| 2-4 | Low | 0.7 |
296
- | 3 |Advanced| 3-5 | Medium | 4.6 |
297
- | 4 |Experienced| 4-5 | High | 9.5 |
582
+ - **Fifty-Move Rule:** The `halfMove` counter is calculated automatically, but the [fifty-move rule](https://en.wikipedia.org/wiki/Fifty-move_rule) is not enforced by the engine. You can implement this rule in your application if needed.
298
583
 
299
- ***Approx. time to move (s)** - This number represent the average amount of seconds needed for one move during a chess game on t3.nano AWS instance.
300
- T3.nano is a low-cost machine with 0.5 GiB RAM and basic CPU performance. Please note, amount of time needed for calculations heavily depends on in-game situation (number of chess pieces still on a chessboard).
584
+ ## TypeScript Support
301
585
 
302
- <BR/>
586
+ Version 2.0 is written entirely in TypeScript and exports all necessary types:
303
587
 
304
- ## HINTS
588
+ ```typescript
589
+ import { Game } from 'js-chess-engine'
590
+ import type {
591
+ // Board types
592
+ BoardConfig,
593
+ PieceSymbol,
594
+ Square,
595
+ Color,
596
+ MovesMap,
597
+ CastlingRights,
598
+ HistoryEntry,
305
599
 
306
- - When a pawn reaches an end of a chessboard, he is automatically converted and calculated as a Queen.
307
- If you like, player can pick a new chess piece in your app, and you can send an updated chessboard.
308
- For in-memory approach please check **setPiece** function.
309
- - Castling can be played by a King. You can receive this special move with `moves` call.
310
- When a move is recognized as a castling - played with a king across two chess fields, rook moves automatically with a king.
311
- - Halfmoves are calculated on the server, but the [fifty-move rule](https://en.wikipedia.org/wiki/Fifty-move_rule) is not handled by a server. You can handle this situation in your app if you need to.
600
+ // AI types
601
+ AILevel,
312
602
 
313
- <BR/>
603
+ // Piece types
604
+ PieceType
605
+ } from 'js-chess-engine'
606
+ ```
607
+
608
+ See `/src/types/board.types.ts` and `/src/types/ai.types.ts` for complete type definitions.
314
609
 
315
610
  ## Collaboration
316
611
 
317
- **Collaborators are welcome.** Please do not forget to check ESLint and run tests before submitting a new pull request (`npm run test`).
612
+ **Collaborators are welcome.** Please ensure your code passes TypeScript type checking and all tests before submitting a pull request:
318
613
 
319
- If it is possible, also use commit message prefixes like `feat: ` or `fix: ` - changelog is generated from this.
614
+ ```bash
615
+ npm run typecheck # TypeScript type checking
616
+ npm run test # Run test suite
617
+ ```
320
618
 
321
- <BR/>
619
+ If possible, use commit message prefixes like `feat:` or `fix:` - the changelog is generated from these.
322
620
 
323
621
  ## TODO
324
- - Calculation and result caching
325
- - Forsyth–Edwards Notation (FEN) validation
326
622
 
327
- <BR/>
623
+ - FEN validation
624
+ - Additional endgame tablebase support
328
625
 
329
626
  ## CHANGELOG
330
- Changelog can be found [HERE](CHANGELOG.md) .
331
627
 
332
- <BR/>
628
+ Changelog can be found [HERE](CHANGELOG.md).
333
629
 
334
630
  ## In conclusion - why another chess engine?
631
+
335
632
  I am not a chess pro. My father is.
336
- When I was ten, I had an Atari (with Turbo Basic), and I was hoping for new PC.
337
- My father told me, make me a computer program, which beat me in chess, and I buy you a new PC.
338
- Obviously, it was a trap and I failed. It comes to my mind after twenty years, and I would like to finish what I started before.
633
+
634
+ When I was ten, I had an Atari (with Turbo Basic), and I was hoping for a new PC. My father told me: "Make me a computer program which beats me in chess, and I'll buy you a new PC."
635
+
636
+ Obviously, it was a trap and I failed. Twenty years later, it came back to my mind, and I decided to finish what I started. This is version 2.0 - a complete TypeScript rewrite with improved performance and architecture.
637
+
638
+ ## Breaking Changes from v1
639
+
640
+ Version 2.0 is a complete TypeScript rewrite with significant API changes. While method names remain the same, **several return types have changed**:
641
+
642
+ ### 1. `moves(square)` Return Type Changed
643
+
644
+ **v1 Behavior:**
645
+
646
+ ```javascript
647
+ const game = new Game()
648
+ game.moves('E2') // Returns array: ["E3", "E4"]
649
+ ```
650
+
651
+ **v2 Behavior:**
652
+
653
+ ```typescript
654
+ const game = new Game()
655
+ game.moves('E2') // Returns object: {"E2": ["E3", "E4"]}
656
+ ```
657
+
658
+ ### 2. `move()` Return Type Changed
659
+
660
+ **v1 Behavior:**
661
+
662
+ ```javascript
663
+ game.move('E2', 'E4') // Returns move object: {"E2": "E4"}
664
+ ```
665
+
666
+ **v2 Behavior:**
667
+
668
+ ```typescript
669
+ game.move('E2', 'E4') // Returns full BoardConfig object
670
+ ```
671
+
672
+ ### 3. `aiMove()` API - Now v1 Compatible ✅
673
+
674
+ The `aiMove()` function has been **restored to v1 API compatibility**.
675
+
676
+ **v1 Behavior:**
677
+
678
+ ```javascript
679
+ aiMove(config, 2) // Returns move object: {"E2": "E4"}
680
+ ```
681
+
682
+ **v2 Behavior (Current):**
683
+
684
+ ```typescript
685
+ aiMove(config, 3) // Returns move object: {"E2": "E4"} ✅ v1 compatible
686
+ ```
687
+
688
+ **New `ai()` function** - For users who need both move and board state:
689
+
690
+ ```typescript
691
+ ai(config, 3) // Returns: { move: {"E2": "E4"}, board: {...} }
692
+ ```
693
+
694
+ ### 4. AI Difficulty Levels Changed
695
+
696
+ - **v1:** Levels 0-4 (0=easiest, 4=hardest)
697
+ - **v2:** Levels 1-5 (1=easiest, 5=hardest)
698
+
699
+ **Migration:**
700
+ - Level 0 → Level 1 (Beginner)
701
+ - Level 1 → Level 2 (Easy)
702
+ - Level 2 → Level 3 (Intermediate, default)
703
+ - Level 3 → Level 4 (Advanced)
704
+ - Level 4 → Level 5 (Expert)
705
+
706
+ The default level has changed from `2` to `3` to maintain similar difficulty in the middle range.
707
+
708
+ ### 5. Node.js Version Requirement
709
+
710
+ - **v1:** Node.js >=20 <21
711
+ - **v2:** Node.js >=24
712
+
713
+ ### What Stayed the Same
714
+
715
+ - ✅ Game class constructor signature
716
+ - ✅ Method names (move, moves, aiMove, etc.)
717
+ - ✅ Board formats (JSON and FEN)
718
+ - ✅ Chess rules (castling, en passant, promotions)
719
+ - ✅ Square notation (case-insensitive: 'E2' or 'e2')