fix(games): fix chess piece interaction and solo mode
Some checks failed
Deploy to Production / test (push) Failing after 32s
Some checks failed
Deploy to Production / test (push) Failing after 32s
Two bugs fixed: - Piece <img> elements were intercepting pointer events, preventing dnd-kit drag handlers and square click handlers from firing. Added pointerEvents: "none" so events pass through to the board framework. - Solo test mode (fillRoom with duplicate player IDs) always resolved to "white" in colorOfPlayer, making black moves impossible. Now detects duplicate IDs and returns the current turn's color instead. Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
This commit is contained in:
@@ -17,7 +17,13 @@ const chessPieces: PieceRenderObject = Object.fromEntries(
|
||||
<img
|
||||
src={`/pieces/${key}.svg`}
|
||||
alt={key}
|
||||
style={{ width: "100%", height: "100%", ...props?.svgStyle }}
|
||||
style={{
|
||||
width: "100%",
|
||||
height: "100%",
|
||||
pointerEvents: "none", // let events pass through to dnd-kit / Square handlers
|
||||
userSelect: "none",
|
||||
...props?.svgStyle,
|
||||
}}
|
||||
draggable={false}
|
||||
/>
|
||||
),
|
||||
@@ -149,7 +155,9 @@ export function ChessGame({ state, myPlayerId, isSpectator, onAction, players }:
|
||||
const view = state as PlayerView | SpectatorView;
|
||||
const playerView = isPlayerView(state) ? state as PlayerView : null;
|
||||
const myColor = playerView?.myColor ?? "white";
|
||||
const boardOrientation = isSpectator ? "white" : myColor;
|
||||
// Solo mode: both players are the same user — myColor flips each turn, so lock orientation to white
|
||||
const isSoloMode = !isSpectator && players.length === 2 && players[0]?.discordId === players[1]?.discordId;
|
||||
const boardOrientation = isSpectator || isSoloMode ? "white" : myColor;
|
||||
const isMyTurn = playerView ? view.turn === playerView.myColor : false;
|
||||
const isGameOver = view.result !== null;
|
||||
const moveHistoryRef = useRef<HTMLDivElement>(null);
|
||||
|
||||
@@ -570,6 +570,38 @@ describe("chessPlugin", () => {
|
||||
});
|
||||
});
|
||||
|
||||
describe("solo mode (duplicate player IDs)", () => {
|
||||
it("should allow the same player to move as both colors", () => {
|
||||
const spy = spyOn(Math, "random").mockReturnValue(0.1);
|
||||
const state = chessPlugin.createInitialState(["alice", "alice"], { timeControl: "none" });
|
||||
spy.mockRestore();
|
||||
// Both white and black are "alice"
|
||||
expect(state.players.white).toBe("alice");
|
||||
expect(state.players.black).toBe("alice");
|
||||
|
||||
// White's turn — alice should be able to move
|
||||
const s1 = act(state, { type: "move", from: "e2", to: "e4" }, "alice");
|
||||
// Black's turn — alice should also be able to move
|
||||
const s2 = act(s1, { type: "move", from: "e7", to: "e5" }, "alice");
|
||||
expect(s2.moveHistory).toHaveLength(2);
|
||||
});
|
||||
|
||||
it("should return the current turn color in player view", () => {
|
||||
const spy = spyOn(Math, "random").mockReturnValue(0.1);
|
||||
const state = chessPlugin.createInitialState(["alice", "alice"], { timeControl: "none" });
|
||||
spy.mockRestore();
|
||||
|
||||
const view1 = chessPlugin.getPlayerView(state, "alice") as ChessPlayerView;
|
||||
expect(view1.myColor).toBe("white"); // White's turn
|
||||
expect(view1.legalMoves.length).toBeGreaterThan(0);
|
||||
|
||||
const s1 = act(state, { type: "move", from: "e2", to: "e4" }, "alice");
|
||||
const view2 = chessPlugin.getPlayerView(s1, "alice") as ChessPlayerView;
|
||||
expect(view2.myColor).toBe("black"); // Black's turn now
|
||||
expect(view2.legalMoves.length).toBeGreaterThan(0);
|
||||
});
|
||||
});
|
||||
|
||||
describe("plugin metadata", () => {
|
||||
it("should have correct slug and name", () => {
|
||||
expect(chessPlugin.slug).toBe("chess");
|
||||
|
||||
@@ -7,8 +7,14 @@ import type {
|
||||
import { TIME_CONTROLS } from "./chess.types";
|
||||
|
||||
function colorOfPlayer(state: ChessState, playerId: string): "white" | "black" | null {
|
||||
if (state.players.white === playerId) return "white";
|
||||
if (state.players.black === playerId) return "black";
|
||||
const isWhite = state.players.white === playerId;
|
||||
const isBlack = state.players.black === playerId;
|
||||
if (isWhite && isBlack) {
|
||||
// Solo test mode — same player controls both sides, return current turn
|
||||
return currentTurn(state.fen);
|
||||
}
|
||||
if (isWhite) return "white";
|
||||
if (isBlack) return "black";
|
||||
return null;
|
||||
}
|
||||
|
||||
|
||||
Reference in New Issue
Block a user