parallel
This commit is contained in:
parent
b4e5e6a5b1
commit
29e88aaf75
|
|
@ -144,14 +144,14 @@ def evalWindow(window, player):
|
||||||
|
|
||||||
score = 0
|
score = 0
|
||||||
if player_count == 4:
|
if player_count == 4:
|
||||||
score += 100
|
score += 100000 # guaranteed win
|
||||||
elif player_count == 3 and empty_count == 1:
|
elif player_count == 3 and empty_count == 1:
|
||||||
score += 50
|
score += 100
|
||||||
elif player_count == 2 and empty_count == 2:
|
elif player_count == 2 and empty_count == 2:
|
||||||
score += 2
|
score += 10
|
||||||
|
|
||||||
if opponent_count == 3 and empty_count == 1:
|
if opponent_count == 3 and empty_count == 1:
|
||||||
score -= 100
|
score -= 120 # prioritize blocking opponent
|
||||||
|
|
||||||
return score
|
return score
|
||||||
|
|
||||||
|
|
@ -209,6 +209,7 @@ def minimax(board, depth, alpha, beta, maximisingPlayer):
|
||||||
return 0
|
return 0
|
||||||
|
|
||||||
allowedMoves = [i for i, col in enumerate(board) if 'O' in col]
|
allowedMoves = [i for i, col in enumerate(board) if 'O' in col]
|
||||||
|
allowedMoves.sort(key=lambda col: abs(3 - col)) # try center → edges
|
||||||
|
|
||||||
if depth == 0 or not allowedMoves:
|
if depth == 0 or not allowedMoves:
|
||||||
return evalPosition(board)
|
return evalPosition(board)
|
||||||
|
|
@ -244,14 +245,28 @@ def minimax(board, depth, alpha, beta, maximisingPlayer):
|
||||||
# | Player move providers |
|
# | Player move providers |
|
||||||
# ===========================
|
# ===========================
|
||||||
def local_move_provider(player, board):
|
def local_move_provider(player, board):
|
||||||
|
# return random.choice([i for i, col in enumerate(board) if 'O' in col])
|
||||||
col = getIntInput(f"{colourTile(player)} where do you want to drop your tile? 1-7.\n>>> ", board) - 1
|
col = getIntInput(f"{colourTile(player)} where do you want to drop your tile? 1-7.\n>>> ", board) - 1
|
||||||
return col
|
return col
|
||||||
|
|
||||||
|
from multiprocessing import Pool
|
||||||
|
|
||||||
|
# --- New helper for multiprocessing ---
|
||||||
|
def evaluate_move(args):
|
||||||
|
move, board, player, depth, maximising = args
|
||||||
|
newBoard = [col.copy() for col in board]
|
||||||
|
tile = newBoard[move].index('O')
|
||||||
|
newBoard[move][tile] = player
|
||||||
|
score = minimax(newBoard, depth - 1, float('-inf'), float('inf'), not maximising)
|
||||||
|
return move, score
|
||||||
|
|
||||||
|
from multiprocessing import Pool
|
||||||
|
|
||||||
def cpu_move_provider(player, board):
|
def cpu_move_provider(player, board):
|
||||||
allowedMoves = [i for i, col in enumerate(board) if 'O' in col]
|
allowedMoves = [i for i, col in enumerate(board) if 'O' in col]
|
||||||
|
|
||||||
best_score = float('-inf') if player == 'R' else float('inf')
|
# Move ordering
|
||||||
best_move = None
|
allowedMoves.sort(key=lambda col: abs(3 - col))
|
||||||
|
|
||||||
try:
|
try:
|
||||||
with open("settings.json", "r") as f:
|
with open("settings.json", "r") as f:
|
||||||
|
|
@ -260,28 +275,18 @@ def cpu_move_provider(player, board):
|
||||||
except (FileNotFoundError, json.JSONDecodeError):
|
except (FileNotFoundError, json.JSONDecodeError):
|
||||||
search_depth = 5
|
search_depth = 5
|
||||||
|
|
||||||
maximising = True if player == 'R' else False
|
maximising = (player == 'R')
|
||||||
|
|
||||||
for move in allowedMoves:
|
# Prepare arguments for pool
|
||||||
newBoard = [col.copy() for col in board]
|
args_list = [(move, board, player, search_depth, maximising) for move in allowedMoves]
|
||||||
tile = newBoard[move].index('O')
|
|
||||||
newBoard[move][tile] = player
|
|
||||||
|
|
||||||
score = minimax(newBoard, search_depth - 1, float('-inf'), float('inf'), not maximising) # because next move is opponent's turn
|
with Pool() as pool:
|
||||||
|
results = pool.map(evaluate_move, args_list)
|
||||||
|
|
||||||
if player == 'R':
|
if player == 'R':
|
||||||
if score > best_score:
|
return max(results, key=lambda x: x[1])[0]
|
||||||
best_score = score
|
|
||||||
best_move = move
|
|
||||||
else:
|
else:
|
||||||
if score < best_score:
|
return min(results, key=lambda x: x[1])[0]
|
||||||
best_score = score
|
|
||||||
best_move = move
|
|
||||||
|
|
||||||
if best_move is None:
|
|
||||||
best_move = random.choice(allowedMoves)
|
|
||||||
|
|
||||||
return best_move
|
|
||||||
|
|
||||||
# ===========================
|
# ===========================
|
||||||
# | Main game loop |
|
# | Main game loop |
|
||||||
|
|
@ -443,7 +448,7 @@ def edit_settings():
|
||||||
if sub_choice.lower() == 'b':
|
if sub_choice.lower() == 'b':
|
||||||
break
|
break
|
||||||
elif sub_choice in ["1","2","3","4","5","6","7","8","9"]:
|
elif sub_choice in ["1","2","3","4","5","6","7","8","9"]:
|
||||||
settings["cpu_search_depth"] = sub_choice
|
settings["cpu_search_depth"] = int(sub_choice)
|
||||||
elif sub_choice in ['+', '-']:
|
elif sub_choice in ['+', '-']:
|
||||||
settings["cpu_search_depth"] = eval(f"{settings["cpu_search_depth"]} {sub_choice}1")
|
settings["cpu_search_depth"] = eval(f"{settings["cpu_search_depth"]} {sub_choice}1")
|
||||||
if settings["cpu_search_depth"] > 9:
|
if settings["cpu_search_depth"] > 9:
|
||||||
|
|
|
||||||
|
|
@ -1,4 +1,4 @@
|
||||||
{
|
{
|
||||||
"display_mode": "coloured_background",
|
"display_mode": "coloured_background",
|
||||||
"cpu_search_depth": 5
|
"cpu_search_depth": 6
|
||||||
}
|
}
|
||||||
Loading…
Reference in New Issue
Block a user