refactor: allow the player to choose kitten to graduate in 8-piece-rule

This commit is contained in:
hyper 2026-04-02 19:56:34 +08:00
parent 793c7d834b
commit 39e1f52f71
2 changed files with 48 additions and 12 deletions

View File

@ -125,6 +125,36 @@ registration.add('turn <player>', async function(cmd) {
processGraduation(this.context, turnPlayer, graduatedLines);
}
if (countPiecesOnBoard(this.context, turnPlayer) >= MAX_PIECES_PER_PLAYER) {
const board = getBoardRegion(this.context);
const partsMap = board.partsMap.value;
const availableKittens: Entity<BoopPart>[] = [];
for (const key in partsMap) {
const part = partsMap[key] as Entity<BoopPart>;
if (part.value.player === turnPlayer && part.value.pieceType === 'kitten') {
availableKittens.push(part);
}
}
if (availableKittens.length > 0) {
const graduateCmd = await this.prompt(
'graduate <row:number> <col:number>',
(command) => {
const [row, col] = command.params as [number, number];
const posKey = `${row},${col}`;
const part = availableKittens.find(p => `${p.value.position[0]},${p.value.position[1]}` === posKey);
if (!part) return `No kitten at (${row}, ${col}).`;
return null;
}
);
const [row, col] = graduateCmd.params as [number, number];
const part = availableKittens.find(p => p.value.position[0] === row && p.value.position[1] === col)!;
removePieceFromBoard(this.context, part);
const playerEntity = getPlayer(this.context, turnPlayer);
incrementSupply(playerEntity, 'cat', 1);
}
}
const winner = checkWinner(this.context);
if (winner) return { winner };
@ -218,9 +248,13 @@ export function applyBoops(host: Entity<BoopState>, placedRow: number, placedCol
export function removePieceFromBoard(host: Entity<BoopState>, part: Entity<BoopPart>) {
const board = getBoardRegion(host);
const playerEntity = getPlayer(host, part.value.player);
board.produce(draft => {
draft.children = draft.children.filter(p => p.id !== part.id);
});
playerEntity.produce(p => {
p[part.value.pieceType].placed--;
});
}
const DIRECTIONS: [number, number][] = [
@ -323,6 +357,17 @@ export function processGraduation(host: Entity<BoopState>, player: PlayerType, l
incrementSupply(playerEntity, 'cat', count);
}
export function countPiecesOnBoard(host: Entity<BoopState>, player: PlayerType): number {
const board = getBoardRegion(host);
const partsMap = board.partsMap.value;
let count = 0;
for (const key in partsMap) {
const part = partsMap[key] as Entity<BoopPart>;
if (part.value.player === player) count++;
}
return count;
}
export function checkWinner(host: Entity<BoopState>): WinnerType {
const board = getBoardRegion(host);
const partsMap = board.partsMap.value;
@ -338,14 +383,5 @@ export function checkWinner(host: Entity<BoopState>): WinnerType {
if (hasWinningLine(positions)) return player;
}
const whitePlayer = getPlayer(host, 'white');
const blackPlayer = getPlayer(host, 'black');
const whiteTotal = MAX_PIECES_PER_PLAYER - whitePlayer.value.kitten.supply + whitePlayer.value.cat.supply;
const blackTotal = MAX_PIECES_PER_PLAYER - blackPlayer.value.kitten.supply + blackPlayer.value.cat.supply;
if (whiteTotal >= MAX_PIECES_PER_PLAYER && blackTotal >= MAX_PIECES_PER_PLAYER) {
return 'draw';
}
return null;
}

View File

@ -30,7 +30,7 @@ On your turn, perform the following steps:
### 1. Placing Pieces
Place one Kitten from your supply onto any empty space on the bed.
Place one piece (Kitten or Cat) from your supply onto any empty space on the bed.
### 2. The "Boop" Mechanic
@ -51,9 +51,9 @@ Placing a piece causes a **"boop."** Every piece (yours or your opponent's) in t
To win, you need Cats. You obtain Cats by lining up Kittens:
1. **Three in a Row:** If you line up three of your Kittens in a row (horizontally, vertically, or diagonally), they "graduate."
2. **The Process:** Remove the three Kittens from the board and return them to the box. Replace them in your personal supply with three **Cats**.
2. **The Process:** Remove the three Kittens from the board and return them to the box. Add three **Cats** to your personal supply.
3. **Multiple Rows:** If placing a piece creates multiple rows of three, you graduate all pieces involved in those rows.
4. **The 8-Piece Rule:** If a player has all 8 of their pieces on the board (a mix of Kittens and Cats) and no one has three-in-a-row, the player must graduate one of their Kittens on the board into a Cat to free up a piece.
4. **The 8-Piece Rule:** If a player has all 8 of their pieces on the board (a mix of Kittens and Cats) and no one has three-in-a-row, the player must choose one of their Kittens on the board to graduate into a Cat to free up a piece.
## How to Win