[fix] Non heuristic moves...
This commit is contained in:
+54
-2
@@ -166,12 +166,57 @@ function scanBoard(b) {
|
||||
return [0, []];
|
||||
}
|
||||
|
||||
function evaluateBoard(b, aiP, huP) {
|
||||
let score = 0;
|
||||
|
||||
// Center column bonus
|
||||
for (let r = 0; r < ROWS; r++) {
|
||||
if (b[3][r] === aiP) score += 3;
|
||||
else if (b[3][r] === huP) score -= 3;
|
||||
}
|
||||
|
||||
// Score a window of 4 cells by piece counts
|
||||
function scoreWindow(c, r, dc, dr) {
|
||||
let ai = 0, hu = 0;
|
||||
for (let i = 0; i < 4; i++) {
|
||||
const v = b[c + i * dc][r + i * dr];
|
||||
if (v === aiP) ai++;
|
||||
else if (v === huP) hu++;
|
||||
}
|
||||
if (ai > 0 && hu > 0) return 0;
|
||||
if (ai === 3) return 50;
|
||||
if (ai === 2) return 5;
|
||||
if (hu === 3) return -50;
|
||||
if (hu === 2) return -5;
|
||||
return 0;
|
||||
}
|
||||
|
||||
// Horizontal
|
||||
for (let r = 0; r < ROWS; r++)
|
||||
for (let c = 0; c <= COLS - 4; c++)
|
||||
score += scoreWindow(c, r, 1, 0);
|
||||
// Vertical
|
||||
for (let r = 0; r <= ROWS - 4; r++)
|
||||
for (let c = 0; c < COLS; c++)
|
||||
score += scoreWindow(c, r, 0, 1);
|
||||
// Diagonal up-right
|
||||
for (let r = 0; r <= ROWS - 4; r++)
|
||||
for (let c = 0; c <= COLS - 4; c++)
|
||||
score += scoreWindow(c, r, 1, 1);
|
||||
// Diagonal down-right
|
||||
for (let r = 3; r < ROWS; r++)
|
||||
for (let c = 0; c <= COLS - 4; c++)
|
||||
score += scoreWindow(c, r, 1, -1);
|
||||
|
||||
return score;
|
||||
}
|
||||
|
||||
// --- AI -----------------------------------------------------
|
||||
function minimax(b, depth, alpha, beta, isMax, aiP, huP) {
|
||||
const [winner] = scanBoard(b);
|
||||
if (winner === aiP) return 1000 + depth;
|
||||
if (winner === huP) return -1000 - depth;
|
||||
if (depth === 0 || isBoardFull(b)) return 0;
|
||||
if (depth === 0 || isBoardFull(b)) return evaluateBoard(b, aiP, huP);
|
||||
|
||||
let best = isMax ? -10000 : 10000;
|
||||
for (const c of COL_ORDER) {
|
||||
@@ -196,12 +241,19 @@ function performAiMove(b, aiP, lookAhead, isDemo = false, dPly = 4) {
|
||||
const huP = aiP === 1 ? 2 : 1;
|
||||
const ply = isDemo ? dPly : lookAhead;
|
||||
|
||||
// Phase 1: instant win / block
|
||||
// Phase 1a: check ALL columns for instant AI win
|
||||
for (let c = 0; c < COLS; c++) {
|
||||
const r = getFirstEmptyRow(b, c);
|
||||
if (r === -1) continue;
|
||||
b[c][r] = aiP;
|
||||
if (scanBoard(b)[0] === aiP) { b[c][r] = 0; return c; }
|
||||
b[c][r] = 0;
|
||||
}
|
||||
|
||||
// Phase 1b: check ALL columns for opponent block
|
||||
for (let c = 0; c < COLS; c++) {
|
||||
const r = getFirstEmptyRow(b, c);
|
||||
if (r === -1) continue;
|
||||
b[c][r] = huP;
|
||||
if (scanBoard(b)[0] === huP) { b[c][r] = 0; return c; }
|
||||
b[c][r] = 0;
|
||||
|
||||
Reference in New Issue
Block a user