diff --git a/connect_four.py b/connect_four.py index 1cf6f26..02376aa 100644 --- a/connect_four.py +++ b/connect_four.py @@ -269,6 +269,57 @@ def log_game(games: list[dict], game_menu_mode: int, level: int, winner: int, mo # --- 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( board: list[list[int]], depth: int, alpha: int, beta: int, is_max: bool, ai_p: int, hu_p: int, @@ -279,7 +330,7 @@ def minimax( if winner == hu_p: return -1000 - depth 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 for c in COL_ORDER: @@ -309,7 +360,7 @@ def perform_ai_move( hu_p = 2 if ai_p == 1 else 1 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): r = get_first_empty_row(board, c) if r != -1: @@ -317,6 +368,12 @@ def perform_ai_move( if scan_board(board)[0] == ai_p: board[c][r] = 0 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 if scan_board(board)[0] == hu_p: board[c][r] = 0