[fix] Add heuristic to Python code.
This commit is contained in:
+59
-2
@@ -269,6 +269,57 @@ def log_game(games: list[dict], game_menu_mode: int, level: int, winner: int, mo
|
|||||||
|
|
||||||
# --- AI ---
|
# --- AI ---
|
||||||
|
|
||||||
|
def evaluate_board(board: list[list[int]], ai_p: int, hu_p: int) -> int:
|
||||||
|
score = 0
|
||||||
|
|
||||||
|
# Center column bonus
|
||||||
|
for r in range(ROWS):
|
||||||
|
if board[3][r] == ai_p:
|
||||||
|
score += 3
|
||||||
|
elif board[3][r] == hu_p:
|
||||||
|
score -= 3
|
||||||
|
|
||||||
|
# Score a window of 4 cells by piece counts
|
||||||
|
def score_window(c: int, r: int, dc: int, dr: int) -> int:
|
||||||
|
ai, hu = 0, 0
|
||||||
|
for i in range(4):
|
||||||
|
v = board[c + i * dc][r + i * dr]
|
||||||
|
if v == ai_p:
|
||||||
|
ai += 1
|
||||||
|
elif v == hu_p:
|
||||||
|
hu += 1
|
||||||
|
if ai > 0 and 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 r in range(ROWS):
|
||||||
|
for c in range(COLS - 3):
|
||||||
|
score += score_window(c, r, 1, 0)
|
||||||
|
# Vertical
|
||||||
|
for r in range(ROWS - 3):
|
||||||
|
for c in range(COLS):
|
||||||
|
score += score_window(c, r, 0, 1)
|
||||||
|
# Diagonal up-right
|
||||||
|
for r in range(ROWS - 3):
|
||||||
|
for c in range(COLS - 3):
|
||||||
|
score += score_window(c, r, 1, 1)
|
||||||
|
# Diagonal down-right
|
||||||
|
for r in range(3, ROWS):
|
||||||
|
for c in range(COLS - 3):
|
||||||
|
score += score_window(c, r, 1, -1)
|
||||||
|
|
||||||
|
return score
|
||||||
|
|
||||||
|
|
||||||
def minimax(
|
def minimax(
|
||||||
board: list[list[int]], depth: int, alpha: int, beta: int,
|
board: list[list[int]], depth: int, alpha: int, beta: int,
|
||||||
is_max: bool, ai_p: int, hu_p: int,
|
is_max: bool, ai_p: int, hu_p: int,
|
||||||
@@ -279,7 +330,7 @@ def minimax(
|
|||||||
if winner == hu_p:
|
if winner == hu_p:
|
||||||
return -1000 - depth
|
return -1000 - depth
|
||||||
if depth == 0 or is_board_full(board):
|
if depth == 0 or is_board_full(board):
|
||||||
return 0
|
return evaluate_board(board, ai_p, hu_p)
|
||||||
|
|
||||||
best = -10000 if is_max else 10000
|
best = -10000 if is_max else 10000
|
||||||
for c in COL_ORDER:
|
for c in COL_ORDER:
|
||||||
@@ -309,7 +360,7 @@ def perform_ai_move(
|
|||||||
hu_p = 2 if ai_p == 1 else 1
|
hu_p = 2 if ai_p == 1 else 1
|
||||||
ply = demo_ply if is_demo else look_ahead
|
ply = demo_ply if is_demo else look_ahead
|
||||||
|
|
||||||
# Phase 1: instant win / block
|
# Phase 1a: check ALL columns for instant AI win
|
||||||
for c in range(COLS):
|
for c in range(COLS):
|
||||||
r = get_first_empty_row(board, c)
|
r = get_first_empty_row(board, c)
|
||||||
if r != -1:
|
if r != -1:
|
||||||
@@ -317,6 +368,12 @@ def perform_ai_move(
|
|||||||
if scan_board(board)[0] == ai_p:
|
if scan_board(board)[0] == ai_p:
|
||||||
board[c][r] = 0
|
board[c][r] = 0
|
||||||
return c
|
return c
|
||||||
|
board[c][r] = 0
|
||||||
|
|
||||||
|
# Phase 1b: check ALL columns for opponent block
|
||||||
|
for c in range(COLS):
|
||||||
|
r = get_first_empty_row(board, c)
|
||||||
|
if r != -1:
|
||||||
board[c][r] = hu_p
|
board[c][r] = hu_p
|
||||||
if scan_board(board)[0] == hu_p:
|
if scan_board(board)[0] == hu_p:
|
||||||
board[c][r] = 0
|
board[c][r] = 0
|
||||||
|
|||||||
Reference in New Issue
Block a user