@fortemate/dicechess-engine-wasm 0.12.3 → 0.13.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/README.md +27 -15
- package/dicechess-engine.d.ts +35 -1
- package/main.js +248 -228
- package/main.wasm +0 -0
- package/main.wasm.map +2 -2
- package/package.json +1 -1
package/README.md
CHANGED
|
@@ -27,7 +27,7 @@ so importing both in the same application loads the shared half once.
|
|
|
27
27
|
|
|
28
28
|
| Import | What it gives you | What it loads |
|
|
29
29
|
| :--- | :--- | :--- |
|
|
30
|
-
| `@fortemate/dicechess-engine` | everything: `DiceChess`, `EngineFacade`, the bots, `getBestMove`, equity, doubling and draw decisions | 1,308,539 B (191,262 B gzipped) |
|
|
30
|
+
| `@fortemate/dicechess-engine` | everything: `DiceChess`, `EngineFacade`, the legal turn tree, the bots, `getBestMove`, equity, doubling and draw decisions | 1,308,539 B (191,262 B gzipped) |
|
|
31
31
|
| `@fortemate/dicechess-engine/rules` | the rules only: `getLegalUciMoves`, `generateMoves`, `applyMove`, `endTurn`, `perft`, `getPieceFromDice`, `canonicalKey` | 891,712 B (138,394 B gzipped) |
|
|
32
32
|
|
|
33
33
|
Use `/rules` wherever the application validates, applies and renders moves but never asks the engine
|
|
@@ -68,44 +68,56 @@ const legalMoves = DiceChess.getLegalUciMoves(dfen);
|
|
|
68
68
|
console.log("Legal moves in this turn:", legalMoves);
|
|
69
69
|
// e.g. ["e2e3", "e2e4", "b1c3", "b1a3", ...]
|
|
70
70
|
|
|
71
|
-
// 2.
|
|
72
|
-
//
|
|
71
|
+
// 2. Get every legal turn as a prefix tree of UCI micro-moves. A node without children is a
|
|
72
|
+
// complete turn. getLegalUciMoves judges each position in isolation, so a client that follows
|
|
73
|
+
// a turn one action at a time walks this tree instead of calling getLegalUciMoves again.
|
|
74
|
+
const turns = DiceChess.getLegalTurnTree(dfen);
|
|
75
|
+
console.log("Continuations of e2e4:", Object.keys(turns["e2e4"]));
|
|
76
|
+
// e.g. ["b1a3", "b1c3", "g1e2", "g1f3", "g1h3"]
|
|
77
|
+
|
|
78
|
+
// 3. Apply a micro-move. applyMove preserves the active color (White), since a Dice Chess turn
|
|
79
|
+
// may consist of multiple micro-moves, and keeps the dice the move did not spend ("N" here).
|
|
73
80
|
// Arguments: (dfen, fromSquare, toSquare, optionalPromotionPiece)
|
|
74
81
|
const nextDfen = DiceChess.applyMove(dfen, "e2", "e4");
|
|
75
82
|
console.log("DFEN after micro-move:", nextDfen);
|
|
76
83
|
|
|
77
|
-
//
|
|
78
|
-
|
|
79
|
-
|
|
80
|
-
|
|
84
|
+
// Spend the knight die too: the turn ends at a leaf of the tree, here after e2e4 then g1f3.
|
|
85
|
+
const turnDfen = DiceChess.applyMove(nextDfen, "g1", "f3");
|
|
86
|
+
|
|
87
|
+
// 4. Explicitly end the turn when the player has exhausted their dice.
|
|
88
|
+
// This toggles the active color to Black, clears the dice pool (the full-move number advances
|
|
89
|
+
// only after Black's turn), and clears any stale en-passant targets from the previous turn.
|
|
90
|
+
const finalDfen = DiceChess.endTurn(turnDfen);
|
|
81
91
|
console.log("DFEN after ending turn:", finalDfen);
|
|
82
92
|
|
|
83
|
-
//
|
|
93
|
+
// 5. Discover available bots (search algorithms)
|
|
84
94
|
const bots = DiceChess.getAvailableBots();
|
|
85
95
|
console.log("Available bots:", bots);
|
|
86
96
|
// e.g. [ { id: 'random', name: 'Random', description: '...', difficulty: 1, isExperimental: false }, ... ]
|
|
87
97
|
|
|
88
|
-
//
|
|
98
|
+
// 6. Discover the built-in time-management policies.
|
|
89
99
|
const timePolicies = DiceChess.getAvailableTimePolicies();
|
|
90
100
|
console.log("Available time policies:", timePolicies);
|
|
91
101
|
// [ "empirical-v1", "legacy-linear-v1" ]
|
|
92
102
|
|
|
93
|
-
//
|
|
103
|
+
// 7. Compute the best sequence of micro-moves using the greedy bot search.
|
|
104
|
+
// The bot needs Black's roll: append the dice (lowercase for Black), here a Pawn and a Knight.
|
|
94
105
|
// Arguments: (dfen, optionalOptions)
|
|
95
|
-
const
|
|
106
|
+
const rolledDfen = `${finalDfen} pn`;
|
|
107
|
+
const botResult = DiceChess.getBestMove(rolledDfen, { algorithm: "greedy" });
|
|
96
108
|
console.log("Bot moves:", botResult.moves);
|
|
97
|
-
// e.g. [ { from: "
|
|
109
|
+
// e.g. [ { from: "b8", to: "c6" }, { from: "a7", to: "a5" } ]
|
|
98
110
|
|
|
99
111
|
// Clock-aware searches use empirical-v1 by default. Pass legacy-linear-v1 to
|
|
100
112
|
// reproduce the original allocation for rollback or an A/B comparison.
|
|
101
|
-
const timedResult = DiceChess.getBestMove(
|
|
113
|
+
const timedResult = DiceChess.getBestMove(rolledDfen, {
|
|
102
114
|
algorithm: "monte-carlo",
|
|
103
115
|
clock: { remainingMs: 180_000, incrementMs: 2_000, moveNumber: 8 },
|
|
104
116
|
timePolicy: "empirical-v1",
|
|
105
117
|
});
|
|
106
118
|
console.log("Effective budget (ms):", timedResult.budgetMs);
|
|
107
119
|
|
|
108
|
-
//
|
|
120
|
+
// 8. Doubling Cube & Draw Offers (New)
|
|
109
121
|
// Check if the bot wants to offer a double before its turn:
|
|
110
122
|
const shouldDouble = DiceChess.shouldBotOfferDouble(finalDfen, 1);
|
|
111
123
|
|
|
@@ -133,7 +145,7 @@ const acceptDraw = DiceChess.shouldBotAcceptDraw(finalDfen);
|
|
|
133
145
|
|
|
134
146
|
## API Reference & Documentation
|
|
135
147
|
|
|
136
|
-
* **[Interactive User & Developer Guide](https://fortemate.
|
|
148
|
+
* **[Interactive User & Developer Guide](https://fortemate.github.io/dicechess-engine/)**: Complete rules, architectural documentation, and live interactive visual catalogs.
|
|
137
149
|
* **[GitHub Repository](https://github.com/fortemate/dicechess-engine)**: Source code, issue tracker, and contribution guidelines.
|
|
138
150
|
|
|
139
151
|
---
|
package/dicechess-engine.d.ts
CHANGED
|
@@ -13,7 +13,10 @@ export interface EngineFacadeApi {
|
|
|
13
13
|
getPieceTypeAt(dfen: string, square: string): number | undefined;
|
|
14
14
|
|
|
15
15
|
/**
|
|
16
|
-
* Applies a move to the given DFEN and returns the resulting state
|
|
16
|
+
* Applies a move to the given DFEN and returns the resulting state, keeping the dice the move
|
|
17
|
+
* did not spend (castling spends the king and the rook die) and, when the DFEN carries dice,
|
|
18
|
+
* refusing a move no die allows.
|
|
19
|
+
* Same as `DiceChess.applyMove`.
|
|
17
20
|
*/
|
|
18
21
|
applyMove(dfen: string, from: string, to: string, promotion?: string): string | undefined;
|
|
19
22
|
|
|
@@ -27,6 +30,20 @@ export interface EngineFacadeApi {
|
|
|
27
30
|
|
|
28
31
|
export const EngineFacade: EngineFacadeApi;
|
|
29
32
|
|
|
33
|
+
/**
|
|
34
|
+
* Every legal turn of a rolled position as a prefix tree of UCI micro-moves, in the shape of
|
|
35
|
+
* dicechess-play-api's `MoveTree`, children in UCI order:
|
|
36
|
+
*
|
|
37
|
+
* { "e2e3": { "e3e4": {} }, "e2e4": { "e4e5": {} } }
|
|
38
|
+
*
|
|
39
|
+
* A node with no children is a complete legal turn, and every complete legal turn is such a leaf:
|
|
40
|
+
* a turn that captures the king ends there, and every other turn spends the most dice the roll
|
|
41
|
+
* allows. An empty object means the roll has no legal move.
|
|
42
|
+
*/
|
|
43
|
+
export interface MoveTree {
|
|
44
|
+
[uci: string]: MoveTree;
|
|
45
|
+
}
|
|
46
|
+
|
|
30
47
|
export type TimePolicyId = "empirical-v1" | "legacy-linear-v1";
|
|
31
48
|
|
|
32
49
|
export interface ClockStateOptions {
|
|
@@ -63,9 +80,21 @@ export interface DiceChessApi {
|
|
|
63
80
|
|
|
64
81
|
/**
|
|
65
82
|
* Returns all legal moves as a flat array of UCI strings (e.g., ["e2e4", "e7e8q"]).
|
|
83
|
+
* They are the legal first actions of a turn from this position, judged in isolation: asked
|
|
84
|
+
* again after each micro-move, the answer can admit actions the whole turn does not allow.
|
|
85
|
+
* Use `getLegalTurnTree` to follow a turn.
|
|
66
86
|
*/
|
|
67
87
|
getLegalUciMoves(dfen: string): string[];
|
|
68
88
|
|
|
89
|
+
/**
|
|
90
|
+
* Returns every legal turn of the rolled position as a prefix tree of UCI micro-moves.
|
|
91
|
+
* Its first level equals `getLegalUciMoves(dfen)`. Deeper levels can be narrower than
|
|
92
|
+
* `getLegalUciMoves` asked again after each micro-move, so a client that follows a turn one
|
|
93
|
+
* action at a time walks this tree. Empty for an invalid DFEN, a DFEN without dice, or a roll
|
|
94
|
+
* with no legal move.
|
|
95
|
+
*/
|
|
96
|
+
getLegalTurnTree(dfen: string): MoveTree;
|
|
97
|
+
|
|
69
98
|
/**
|
|
70
99
|
* Executes perft (performance test) counting leaf nodes at given depth.
|
|
71
100
|
* @param dfen The position in DFEN notation.
|
|
@@ -119,6 +148,11 @@ export interface DiceChessApi {
|
|
|
119
148
|
|
|
120
149
|
/**
|
|
121
150
|
* Applies a move to the given DFEN and returns the resulting state.
|
|
151
|
+
* The result keeps the dice the move did not spend; castling spends the king and the rook die.
|
|
152
|
+
* Pass it back unchanged: while dice remain, appending dice to it yields an eight-field DFEN,
|
|
153
|
+
* which is rejected. `undefined` when the move is not pseudo-legal, when no die in the pool
|
|
154
|
+
* allows it, or when an argument is invalid. A position without dice, including the one
|
|
155
|
+
* returned once the last die is spent, accepts any pseudo-legal move.
|
|
122
156
|
* @param dfen The starting board state in DiceChess FEN notation.
|
|
123
157
|
* @param from The algebraic notation of the starting square.
|
|
124
158
|
* @param to The algebraic notation of the target square.
|