2026-04-04 15:27:37 +08:00
|
|
|
|
# 棋子、区域与 RNG
|
|
|
|
|
|
|
|
|
|
|
|
## 创建和放置 Part
|
|
|
|
|
|
|
|
|
|
|
|
```ts
|
2026-04-04 22:42:23 +08:00
|
|
|
|
import { createPart, createRegion, moveToRegion } from 'boardgame-core';
|
2026-04-04 15:27:37 +08:00
|
|
|
|
|
|
|
|
|
|
const board = createRegion('board', [
|
|
|
|
|
|
{ name: 'row', min: 0, max: 2 },
|
|
|
|
|
|
{ name: 'col', min: 0, max: 2 },
|
|
|
|
|
|
]);
|
|
|
|
|
|
|
|
|
|
|
|
const piece = createPart<{ owner: string }>(
|
2026-04-04 22:42:23 +08:00
|
|
|
|
{ regionId: '', position: [], owner: 'white' },
|
2026-04-04 15:27:37 +08:00
|
|
|
|
'piece-1'
|
|
|
|
|
|
);
|
|
|
|
|
|
|
|
|
|
|
|
state.produce(draft => {
|
|
|
|
|
|
draft.parts[piece.id] = piece;
|
2026-04-04 22:42:23 +08:00
|
|
|
|
// 推荐使用 moveToRegion 自动维护 childIds 和 partMap
|
|
|
|
|
|
moveToRegion(piece, null, draft.board, [1, 1]);
|
2026-04-04 15:27:37 +08:00
|
|
|
|
});
|
2026-04-04 22:42:23 +08:00
|
|
|
|
|
|
|
|
|
|
// 或者手动操作(不推荐,容易出错):
|
|
|
|
|
|
// state.produce(draft => {
|
|
|
|
|
|
// draft.parts[piece.id] = piece;
|
|
|
|
|
|
// draft.board.childIds.push(piece.id);
|
|
|
|
|
|
// draft.board.partMap['1,1'] = piece.id;
|
|
|
|
|
|
// piece.regionId = 'board';
|
|
|
|
|
|
// piece.position = [1, 1];
|
|
|
|
|
|
// });
|
2026-04-04 15:27:37 +08:00
|
|
|
|
```
|
|
|
|
|
|
|
|
|
|
|
|
## Part 池
|
|
|
|
|
|
|
|
|
|
|
|
```ts
|
|
|
|
|
|
const pool = createPartPool<{ type: string }>(
|
|
|
|
|
|
{ regionId: 'supply', type: 'kitten' },
|
|
|
|
|
|
10,
|
|
|
|
|
|
'kitten'
|
|
|
|
|
|
);
|
|
|
|
|
|
|
|
|
|
|
|
const piece = pool.draw(); // 取出一个
|
|
|
|
|
|
pool.return(piece); // 放回
|
|
|
|
|
|
pool.remaining(); // 剩余数量
|
|
|
|
|
|
```
|
|
|
|
|
|
|
2026-04-04 22:19:36 +08:00
|
|
|
|
## 从表格数据创建 Part
|
2026-04-04 15:27:37 +08:00
|
|
|
|
|
|
|
|
|
|
```ts
|
2026-04-04 22:19:36 +08:00
|
|
|
|
const parts = createPartsFromTable(
|
|
|
|
|
|
[
|
2026-04-04 22:42:23 +08:00
|
|
|
|
{ id: 'p1', regionId: 'board', position: [0, 0], owner: 'white' },
|
|
|
|
|
|
{ id: 'p2', regionId: 'board', position: [1, 1], owner: 'black' },
|
2026-04-04 22:19:36 +08:00
|
|
|
|
],
|
2026-04-04 22:42:23 +08:00
|
|
|
|
(item, index) => item.id, // 返回 ID 的函数
|
|
|
|
|
|
// 可选:每个 item 创建几个,默认 1
|
|
|
|
|
|
1
|
2026-04-04 22:19:36 +08:00
|
|
|
|
);
|
2026-04-04 22:42:23 +08:00
|
|
|
|
|
|
|
|
|
|
// parts = {
|
|
|
|
|
|
// 'p1': { id: 'p1', regionId: 'board', position: [0, 0], owner: 'white' },
|
|
|
|
|
|
// 'p2': { id: 'p2', regionId: 'board', position: [1, 1], owner: 'black' },
|
|
|
|
|
|
// }
|
2026-04-04 22:19:36 +08:00
|
|
|
|
```
|
2026-04-04 15:27:37 +08:00
|
|
|
|
|
2026-04-04 22:42:23 +08:00
|
|
|
|
`createPartsFromTable` 接受对象数组,每个对象的所有字段都会被展开到 Part 中。
|
|
|
|
|
|
|
2026-04-04 22:19:36 +08:00
|
|
|
|
## 查询棋子
|
|
|
|
|
|
|
|
|
|
|
|
```ts
|
|
|
|
|
|
// O(n) 遍历查找
|
|
|
|
|
|
findPartById(state.parts, 'piece-1');
|
|
|
|
|
|
getPartAtPosition(state.parts, 'board', [1, 1]);
|
2026-04-04 15:27:37 +08:00
|
|
|
|
isCellOccupied(state.parts, 'board', [1, 1]);
|
2026-04-04 22:19:36 +08:00
|
|
|
|
|
|
|
|
|
|
// O(1) 使用 Region.partMap 查找
|
|
|
|
|
|
getPartAtPositionInRegion(board, state.parts, [1, 1]);
|
|
|
|
|
|
isCellOccupiedByRegion(board, [1, 1]);
|
|
|
|
|
|
```
|
|
|
|
|
|
|
|
|
|
|
|
## 区域操作
|
|
|
|
|
|
|
|
|
|
|
|
```ts
|
|
|
|
|
|
import { applyAlign, shuffle, moveToRegion } from 'boardgame-core';
|
|
|
|
|
|
|
2026-04-04 15:27:37 +08:00
|
|
|
|
applyAlign(handRegion, state.parts); // 紧凑排列
|
|
|
|
|
|
shuffle(deckRegion, state.parts, rng); // 打乱
|
2026-04-04 22:42:23 +08:00
|
|
|
|
|
|
|
|
|
|
// 移动棋子:sourceRegion 为 null 表示棋子当前不在区域中
|
2026-04-04 15:27:37 +08:00
|
|
|
|
moveToRegion(piece, sourceRegion, targetRegion, [0, 0]);
|
2026-04-04 22:42:23 +08:00
|
|
|
|
moveToRegion(piece, null, boardRegion, [0, 0]); // 从外部放入区域
|
|
|
|
|
|
moveToRegion(piece, boardRegion, null); // 从区域中移除(返回外部)
|
2026-04-04 15:27:37 +08:00
|
|
|
|
```
|
|
|
|
|
|
|
2026-04-04 22:19:36 +08:00
|
|
|
|
## 翻面与掷骰
|
|
|
|
|
|
|
|
|
|
|
|
```ts
|
|
|
|
|
|
import { flip, flipTo, roll } from 'boardgame-core';
|
|
|
|
|
|
|
|
|
|
|
|
flip(piece); // 翻到下一面
|
|
|
|
|
|
flipTo(piece, 2); // 翻到指定面
|
|
|
|
|
|
roll(piece, rng); // 随机面
|
|
|
|
|
|
```
|
|
|
|
|
|
|
2026-04-04 15:27:37 +08:00
|
|
|
|
## RNG
|
|
|
|
|
|
|
|
|
|
|
|
```ts
|
|
|
|
|
|
import { createRNG } from 'boardgame-core';
|
|
|
|
|
|
|
|
|
|
|
|
const rng = createRNG(12345);
|
|
|
|
|
|
rng.nextInt(6); // 0-5
|
|
|
|
|
|
rng.next(); // [0, 1)
|
|
|
|
|
|
```
|
|
|
|
|
|
|
|
|
|
|
|
完整 API 列表详见 [API 参考](./api-reference.md)。
|