perf(ai): optimize AI decision speed — fast clone, reduced search, time budget
SCOPONE-0005 iteration 8 - Replace JSON.parse/stringify deepClone with hand-written cloneState() (~10-50x faster) - Export cloneState from engine.ts, use in applyMove and generateSamples - Master: reduce samples 24→10 (14 endgame), depth 8→6 (8 endgame) - Add 1.5s time budget with early termination in masterMove and alphaBeta - evaluateFast(): single-pass pile scan, zero array allocations at leaf nodes - Simplified move ordering in alphaBeta (captures-first, no per-move eval) - Skip countScopaThreats when tableSum >= 11 (impossible to clear) - Remove unused calcPrimiera import from ai.ts
This commit is contained in:
@@ -126,7 +126,7 @@ export function applyMove(
|
||||
card: Card,
|
||||
captureChoice?: Card[]
|
||||
): { nextState: GameState; capture: Capture | null; isScopa: boolean } {
|
||||
const state2 = deepClone(state);
|
||||
const state2 = cloneState(state);
|
||||
const player = state2.players[playerIdx];
|
||||
|
||||
// Remove card from hand
|
||||
@@ -294,6 +294,43 @@ export function getScoreBreakdown(state: GameState): ScoreBreakdown {
|
||||
// Helpers
|
||||
// ---------------------------------------------------------------------------
|
||||
|
||||
function cloneCard(c: Card): Card {
|
||||
return { suit: c.suit, value: c.value, id: c.id };
|
||||
}
|
||||
|
||||
function clonePlayer(p: Player): Player {
|
||||
return {
|
||||
index: p.index,
|
||||
hand: p.hand.map(cloneCard),
|
||||
pile: p.pile.map(cloneCard),
|
||||
scope: p.scope,
|
||||
isHuman: p.isHuman,
|
||||
name: p.name,
|
||||
};
|
||||
}
|
||||
|
||||
function cloneTeamScore(ts: TeamScore): TeamScore {
|
||||
return { ...ts };
|
||||
}
|
||||
|
||||
export function cloneState(state: GameState): GameState {
|
||||
return {
|
||||
players: [
|
||||
clonePlayer(state.players[0]),
|
||||
clonePlayer(state.players[1]),
|
||||
clonePlayer(state.players[2]),
|
||||
clonePlayer(state.players[3]),
|
||||
],
|
||||
table: state.table.map(cloneCard),
|
||||
currentPlayer: state.currentPlayer,
|
||||
roundOver: state.roundOver,
|
||||
gameOver: state.gameOver,
|
||||
teamScores: [cloneTeamScore(state.teamScores[0]), cloneTeamScore(state.teamScores[1])],
|
||||
lastCapturTeam: state.lastCapturTeam,
|
||||
roundNumber: state.roundNumber,
|
||||
};
|
||||
}
|
||||
|
||||
function deepClone<T>(obj: T): T {
|
||||
return JSON.parse(JSON.stringify(obj));
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user