This commit is contained in:
Nikolaj Danger
2020-08-12 13:45:05 +02:00
parent e9e08ef0d6
commit 25da2cc3eb
2 changed files with 16 additions and 20 deletions

View File

@@ -2,6 +2,7 @@ import json
import random import random
import copy import copy
import math import math
import asyncio
from . import fourInARowDraw from . import fourInARowDraw
from funcs import logThis, getName, getID from funcs import logThis, getName, getID
@@ -13,7 +14,7 @@ AIScores = {
"enemy two in a row": -35, "enemy two in a row": -35,
"enemy three in a row": -200, "enemy three in a row": -200,
"enemy win": -10000, "enemy win": -10000,
"win": 1000, "win": 10000,
"avoid losing": 100 "avoid losing": 100
} }
@@ -232,7 +233,7 @@ def isWon(board):
return won, winDirection, winCoordinates return won, winDirection, winCoordinates
# Plays as the AI # Plays as the AI
def fourInARowAI(channel): async def fourInARowAI(channel):
logThis("Figuring out best move") logThis("Figuring out best move")
with open("resources/games/games.json", "r") as f: with open("resources/games/games.json", "r") as f:
data = json.load(f) data = json.load(f)
@@ -246,7 +247,7 @@ def fourInARowAI(channel):
testBoard = copy.deepcopy(board) testBoard = copy.deepcopy(board)
testBoard = placeOnBoard(testBoard,player,column) testBoard = placeOnBoard(testBoard,player,column)
if testBoard != None: if testBoard != None:
scores[column] = minimax(testBoard,difficulty,player%2+1,player,-math.inf,math.inf,False) scores[column] = await minimax(testBoard,difficulty,player%2+1,player,-math.inf,math.inf,False)
logThis("Best score for column "+str(column)+" is "+str(scores[column])) logThis("Best score for column "+str(column)+" is "+str(scores[column]))
possibleScores = scores.copy() possibleScores = scores.copy()
@@ -266,12 +267,10 @@ def AICalcPoints(board,player):
otherPlayer = player%2+1 otherPlayer = player%2+1
# Adds points for middle placement # Adds points for middle placement
for row in range(len(board)):
if board[row][3] == player:
score += AIScores["middle"]
# Checks horizontal # Checks horizontal
for row in range(rowCount): for row in range(rowCount):
if board[row][3] == player:
score += AIScores["middle"]
rowArray = [int(i) for i in list(board[row])] rowArray = [int(i) for i in list(board[row])]
for place in range(columnCount-3): for place in range(columnCount-3):
window = rowArray[place:place+4] window = rowArray[place:place+4]
@@ -290,8 +289,6 @@ def AICalcPoints(board,player):
window = [board[row][place],board[row+1][place+1],board[row+2][place+2],board[row+3][place+3]] window = [board[row][place],board[row+1][place+1],board[row+2][place+2],board[row+3][place+3]]
score += evaluateWindow(window,player,otherPlayer) score += evaluateWindow(window,player,otherPlayer)
# Checks left diagonal
for row in range(rowCount-3):
for place in range(3,columnCount): for place in range(3,columnCount):
window = [board[row][place],board[row+1][place-1],board[row+2][place-2],board[row+3][place-3]] window = [board[row][place],board[row+1][place-1],board[row+2][place-2],board[row+3][place-3]]
score += evaluateWindow(window,player,otherPlayer) score += evaluateWindow(window,player,otherPlayer)
@@ -319,11 +316,12 @@ def evaluateWindow(window,player,otherPlayer):
else: else:
return 0 return 0
def minimax(board, depth, player , originalPlayer, alpha, beta, maximizingPlayer): async def minimax(board, depth, player , originalPlayer, alpha, beta, maximizingPlayer):
terminal = ((isWon(board)[0] != 0) or (0 not in board[0])) #terminal = ((0 not in board[0]) or (isWon(board)[0] != 0))
terminal = 0 not in board[0]
points = AICalcPoints(board,originalPlayer)
# The depth is how many moves ahead the computer checks. This value is the difficulty. # The depth is how many moves ahead the computer checks. This value is the difficulty.
if depth == 0 or terminal: if depth == 0 or terminal or (points > 5000 or points < -6000):
points = AICalcPoints(board,originalPlayer)
return points return points
if maximizingPlayer: if maximizingPlayer:
value = -math.inf value = -math.inf
@@ -331,12 +329,11 @@ def minimax(board, depth, player , originalPlayer, alpha, beta, maximizingPlayer
testBoard = copy.deepcopy(board) testBoard = copy.deepcopy(board)
testBoard = placeOnBoard(testBoard,player,column) testBoard = placeOnBoard(testBoard,player,column)
if testBoard != None: if testBoard != None:
evaluation = minimax(testBoard,depth-1,player%2+1,originalPlayer,alpha,beta,False) evaluation = await minimax(testBoard,depth-1,player%2+1,originalPlayer,alpha,beta,False)
if evaluation < -9000: evaluation += AIScores["avoid losing"] if evaluation < -9000: evaluation += AIScores["avoid losing"]
value = max(value,evaluation) value = max(value,evaluation)
alpha = max(alpha,evaluation) alpha = max(alpha,evaluation)
if beta <= alpha: if beta <= alpha: break
break
return value return value
else: else:
value = math.inf value = math.inf
@@ -344,10 +341,9 @@ def minimax(board, depth, player , originalPlayer, alpha, beta, maximizingPlayer
testBoard = copy.deepcopy(board) testBoard = copy.deepcopy(board)
testBoard = placeOnBoard(testBoard,player,column) testBoard = placeOnBoard(testBoard,player,column)
if testBoard != None: if testBoard != None:
evaluation = minimax(testBoard,depth-1,player%2+1,originalPlayer,alpha,beta,True) evaluation = await minimax(testBoard,depth-1,player%2+1,originalPlayer,alpha,beta,True)
if evaluation < -9000: evaluation += AIScores["avoid losing"] if evaluation < -9000: evaluation += AIScores["avoid losing"]
value = min(value,evaluation) value = min(value,evaluation)
beta = min(beta,evaluation) beta = min(beta,evaluation)
if beta <= alpha: if beta <= alpha: break
break
return value return value

View File

@@ -94,7 +94,7 @@ async def fiar(channel,command,user):
if gameDone == False: if gameDone == False:
if gwendoTurn: if gwendoTurn:
try: try:
response, showImage, deleteImage, gameDone, gwendoTurn = fourInARowAI(str(channel.id)) response, showImage, deleteImage, gameDone, gwendoTurn = await fourInARowAI(str(channel.id))
except: except:
logThis("AI error (error code 1420)") logThis("AI error (error code 1420)")
await channel.send(response) await channel.send(response)