Skip to content

Commit 800a1e9

Browse files
committed
Large board perf: depth cap, gate mobility bonus, skip threat markers when disabled, scrollable game board
1 parent cab1453 commit 800a1e9

3 files changed

Lines changed: 32 additions & 8 deletions

File tree

src/components/Board.tsx

Lines changed: 6 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -95,7 +95,9 @@ export function Board({ flipped = false }: Props) {
9595
mode.kind === "two-player" &&
9696
!store.settings.autoFlip &&
9797
store.settings.rotateBlackPiecesFixedBoard;
98+
const showThreats = store.settings.showThreats;
9899
const legalCaptureTargets = useMemo(() => {
100+
if (!showThreats) return { w: new Set<string>(), b: new Set<string>() };
99101
const whiteTargets = new Set(
100102
allLegalMoves({ ...state, turn: "w" })
101103
.filter((move) => Boolean(move.captured))
@@ -107,7 +109,7 @@ export function Board({ flipped = false }: Props) {
107109
.map((move) => squareKey(move.to))
108110
);
109111
return { w: whiteTargets, b: blackTargets };
110-
}, [state]);
112+
}, [state, showThreats]);
111113

112114
useLayoutEffect(() => {
113115
const current = state.history[state.history.length - 1];
@@ -157,7 +159,9 @@ export function Board({ flipped = false }: Props) {
157159
className={`board board-theme-${theme} piece-set-${pieceSet} anim-speed-${animationSpeed}`}
158160
style={{
159161
aspectRatio: `${fileCount} / ${rankCount}`,
160-
["--square-font-size" as string]: `${squareFontSize}px`
162+
["--square-font-size" as string]: `${squareFontSize}px`,
163+
["--file-count" as string]: fileCount,
164+
["--rank-count" as string]: rankCount,
161165
}}
162166
>
163167
{ranks.map((r) => (

src/engine/bot.ts

Lines changed: 10 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -19,9 +19,13 @@ function materialScore(state: GameState, color: "w" | "b"): number {
1919
const v = p.type === "X1" ? customPieceValueForDef(state, p) : (VALUES[p.type] ?? 0);
2020
s += (p.color === color ? 1 : -1) * v;
2121
}
22-
// Slight mobility bonus
23-
const moves = allLegalMoves(state).length;
24-
s += (state.turn === color ? moves : -moves) * 2;
22+
// Mobility bonus: reward having more legal moves than the opponent.
23+
// Only compute this at the leaf level; skip for large boards to keep it fast.
24+
const boardArea = boardWidth(state) * boardHeight(state);
25+
if (boardArea <= 100) {
26+
const moves = allLegalMoves(state).length;
27+
s += (state.turn === color ? moves : -moves) * 2;
28+
}
2529
return s;
2630
}
2731

@@ -115,7 +119,9 @@ export async function chooseBotMove(state: GameState, level: number, opts?: BotO
115119
// Level 6+: deterministic minimax fallback if external engine is unavailable.
116120
const blunderChanceByLevel: Record<number, number> = { 1: 0.8, 2: 0.5, 3: 0.15, 4: 0.03 };
117121
const blunderChance = blunderChanceByLevel[normalizedLevel] ?? 0;
118-
const depth = normalizedLevel <= 2 ? 1 : normalizedLevel <= 4 ? 2 : normalizedLevel <= 8 ? 3 : 4;
122+
const boardArea = boardWidth(state) * boardHeight(state);
123+
const depthCap = boardArea > 200 ? 1 : boardArea > 100 ? 2 : 4;
124+
const depth = Math.min(depthCap, normalizedLevel <= 2 ? 1 : normalizedLevel <= 4 ? 2 : normalizedLevel <= 8 ? 3 : 4);
119125

120126
if (rng() < blunderChance) {
121127
const captures = moves.filter((m) => m.captured);

src/styles.css

Lines changed: 16 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -182,14 +182,24 @@ section label { display: block; margin: 6px 0; }
182182
flex-direction: column;
183183
width: 100%;
184184
max-width: 560px;
185-
aspect-ratio: 1 / 1;
186185
margin: 12px auto;
187186
border: 2px solid #111;
188187
border-radius: 8px;
189188
overflow: hidden;
190189
user-select: none;
191190
}
192191
.board-row { display: flex; flex: 1; }
192+
/* On mobile, force a minimum 40px cell so large boards scroll rather than squish */
193+
@media (max-width: 640px) {
194+
.board {
195+
min-width: calc(var(--file-count, 8) * 40px);
196+
min-height: calc(var(--rank-count, 8) * 40px);
197+
width: calc(var(--file-count, 8) * 40px);
198+
max-width: none;
199+
}
200+
.board-row { flex: none; height: 40px; }
201+
.square { flex: none; width: 40px; height: 40px; }
202+
}
193203
.square {
194204
flex: 1;
195205
position: relative;
@@ -1159,7 +1169,11 @@ section label { display: block; margin: 6px 0; }
11591169
.puzzle-controls { margin: 10px 0; justify-content: space-between; }
11601170
.topbar .muted { color: #94a3b8; font-size: 0.9rem; }
11611171

1162-
.board-wrap { position: relative; }
1172+
.board-wrap {
1173+
position: relative;
1174+
overflow: auto;
1175+
-webkit-overflow-scrolling: touch;
1176+
}
11631177
.pause-overlay {
11641178
position: absolute; inset: 0;
11651179
display: flex; align-items: center; justify-content: center;

0 commit comments

Comments
 (0)