def hFunction(self, board): PlayerID = self.ID opponentID = PlayerID * -1 if winningTest(PlayerID, board, X_IN_A_LINE): return +100 if winningTest(opponentID, board, X_IN_A_LINE): return -100 base = 2 val = (Player.straightFourCount(board, PlayerID) * pow(base, 4) * 1.2 + \ Player.fourInARowCount(board, PlayerID) * pow(base, 4) + \ Player.straightThreeCount(board, PlayerID) * pow(base, 3) + \ Player.brokenThreeCount(board, PlayerID) * pow(base, 3) + \ Player.twoInARow(board, PlayerID) * pow(base, 2) + Player.brokenTwoInARow(board, PlayerID) + Player.singleCount(board, PlayerID)) \ - \ (Player.straightFourCount(board, opponentID) * pow(base, 4) * 1.2 + \ Player.fourInARowCount(board, opponentID) * pow(base, 4) + \ Player.straightThreeCount(board, opponentID) * pow(base, 3) + \ Player.brokenThreeCount(board, opponentID) * pow(base, 3) + \ Player.twoInARow(board, opponentID) * pow(base, 2) + Player.brokenTwoInARow(board, opponentID) + Player.singleCount(board, opponentID)) return val
def terminal_test(self, board): flag = False if winningTest(self.ID, board, self.X_IN_A_LINE) or winningTest( -self.ID, board, self.X_IN_A_LINE): flag = True if len(self.actions(board)) == 0: flag = True return flag
def turn(board, player, turn_id): # make a copy of the board, which is passed to the agent tempBoard = np.array(board) # TIME_OUT seconds Timer try: with concurrent.futures.ThreadPoolExecutor() as executor: playerThread = executor.submit(player.move, tempBoard) moveLoc = playerThread.result(TIME_OUT + 1) except TimeOutException: # Caught the signal timeout exception print("before pass") pass except concurrent.futures.TimeoutError: print("Player" + str(turn_id) + " time out.") return turn_id * 1, board # test if the move is legal - on the original board if legalMove(board, moveLoc): board[moveLoc] = player.ID else: print("Player " + str(player.ID) + " illegal move at " + str(moveLoc)) return turn_id * -1, board # test if any player wins the game if winningTest(player.ID, board, X_IN_A_LINE): return turn_id, board # move to the next turn return 0, board
def max_value(self, board, depth, alpha, beta): print("depth is:{d}".format(d=depth)) if depth==2: return self.evaluate_board( board) if winningTest(self.opp_id, board, self.X_IN_A_LINE): return self.evaluate_board(board) value = -99999 temp_v = self.evaluate_board(board) print("max") print(board) print("value is: {v}".format(v=temp_v)) if temp_v>=0: possi_moves = self.find_my_moves(board) else: possi_moves = self.find_opp_moves(board) for move in possi_moves: print("({r},{c})".format(r=move[0], c=move[1])) board[move[0],move[1]]=self.ID value= max(value, self.min_value(board,depth+1, alpha, beta)) board[move[0],move[1]]=0 print(beta) if value>=beta: return value alpha = max(alpha, value) return value
def max_value(self, board, alpha, beta, depth): if (winningTest(self.opp_id, board, self.X_IN_A_LINE) or depth == 2): # Depth 2 was chosen to terminate, the AI will lose because of timeout if I go deeper return (self.evaluate_move(board), (0, 0)) value = -99999999 possi_moves = self.find_moves(board, True) possi_moves = list(dict.fromkeys(possi_moves)) # Remove duplicates best = (value, (0, 0)) for move, v in possi_moves: board[move[0], move[1]] = self.ID va, act = self.min_value(board, alpha, beta, depth + 1) cur_value = (va, move) best = max(best, cur_value, key=lambda item: item[0]) board[move[0], move[1]] = 0 if best[0] >= beta: return best alpha = max(alpha, best[0]) return best
def min_value(self, board, alpha, beta, depth): if (winningTest(self.ID, board, self.X_IN_A_LINE)): return (self.evaluate_move(board), (0, 0)) value = 99999999 possi_moves = self.find_moves(board, False) possi_moves = list(dict.fromkeys(possi_moves)) best = (value, (0, 0)) for move, v in possi_moves: board[move[0], move[1]] = self.opp_id va, act = self.max_value(board, alpha, beta, depth + 1) cur_value = (va, move) best = min(best, cur_value, key=lambda item: item[0]) board[move[0], move[1]] = 0 if best[0] <= alpha: return best beta = min(beta, best[0]) return best
def turn(board, player): # set the time out alarm and call player's move function signal.alarm(TIME_OUT) try: moveLoc = player.move(board) except timeOutException: return player.ID * -1, board signal.alarm(0) # test if the move is legal if legalMove(board, moveLoc): board[moveLoc] = player.ID else: return player.ID * -1, board # test if any player wins the game if winningTest(player.ID, board, X_IN_A_LINE): return player.ID, board # move to the next turn return 0, board
def getHeuristics(self, board): figs2VH, figs3VH, figs4VH = boardValRow( self, board, self.ID) #GET figures of specified player horizonta and vertical figs2Diag, figs3Diag, figs4Diag = boardValDiag(self, board, self.ID) #DIagonal figs2VHEnemy, figs3VHEnemy, figs4VHEnemy = boardValRow( self, board, -self.ID) #GET figures of specified player horizonta and vertical figs2DiagEnemy, figs3DiagEnemy, figs4DiagEnemy = boardValDiag( self, board, -self.ID) #DIagonal priorityValid2, normalValid2 = isPotentialWin(board, figs2VH + figs2Diag, 2, self.ID) priorityValid3, normalValid3 = isPotentialWin(board, figs3VH + figs3Diag, 3, self.ID) priorityValid4, normalValid4 = isPotentialWin(board, figs4VH + figs4Diag, 4, self.ID) priorityValid2Enemy, normalValid2Enemy = isPotentialWin( board, figs2VHEnemy + figs2DiagEnemy, 2, -self.ID) priorityValid3Enemy, normalValid3Enemy = isPotentialWin( board, figs3VHEnemy + figs3DiagEnemy, 3, -self.ID) priorityValid4Enemy, normalValid4Enemy = isPotentialWin( board, figs4VHEnemy + figs4DiagEnemy, 4, -self.ID) fig4Value = 0 fig4ValueEnemy = 0 fig3ValueP = 0 fig3ValuePEnemy = 0 fig3ValueN = 0 fig3ValueNEnemy = 0 fig2ValueP = 0 fig2ValuePEnemy = 0 fig2ValueN = 0 fig2ValueNEnemy = 0 borderValue = 0 borderValueEnemy = 0 finalValue = 0 finalValueEnemy = 0 if (priorityValid4 or priorityValid3 or priorityValid2): VALUE_5 = 9999 VALUE_4 = 4000 VALUE_3_P = 1000 VALUE_3_N = 100 VALUE_2_P = 1000 VALUE_2_N = 20 else: VALUE_5 = 9999 VALUE_4 = 4000 VALUE_3_P = 1000 VALUE_3_N = 100 VALUE_2_P = 1000 VALUE_2_N = 20 for fig in priorityValid4: fig4Value = fig4Value + VALUE_4 for fig in priorityValid3: fig3ValueP = fig3ValueP + VALUE_3_P for fig in normalValid3: fig3ValueN = fig3ValueN + VALUE_3_N for fig in priorityValid2: fig2ValueP = fig2ValueP + VALUE_2_P for fig in normalValid2: fig2ValueN = fig2ValueN + VALUE_2_N for fig in priorityValid4Enemy: fig4ValueEnemy = fig4ValueEnemy + VALUE_4 for fig in priorityValid3Enemy: fig3ValuePEnemy = fig3ValuePEnemy + VALUE_3_P for fig in normalValid3Enemy: fig3ValueNEnemy = fig3ValueNEnemy + VALUE_3_N for fig in priorityValid2Enemy: fig2ValuePEnemy = fig2ValuePEnemy + VALUE_2_P for fig in normalValid2Enemy: fig2ValueNEnemy = fig2ValueNEnemy + VALUE_2_N borderValue = getBorderValue(board, self.ID) borderValueEnemy = getBorderValue(board, -self.ID) finalValueFig = fig4Value + fig3ValueP + fig3ValueN + fig2ValueP + fig2ValueN finalValueFigEnemy = fig4ValueEnemy + fig3ValuePEnemy + fig3ValueNEnemy + fig2ValuePEnemy + fig2ValueNEnemy finalValue = finalValueFig + borderValue finalValueEnemy = finalValueFigEnemy + borderValueEnemy #SHOULD BE BORDERVALUE, but maybe not?? if winningTest(self.ID, board, self.X_IN_A_LINE): finalValue += VALUE_5 if winningTest(-self.ID, board, self.X_IN_A_LINE): finalValueEnemy += VALUE_5 returnValue = finalValue - finalValueEnemy return returnValue
def block_closed_four(self, board, l_moves): for pos in l_moves: copy = self.result(board, pos, -self.ID) if winningTest(-self.ID, copy, self.X_IN_A_LINE): return True, pos return False, None
def immediate_win_position(self, board, l_moves): for pos in l_moves: copy = self.result(board, pos, self.ID) if winningTest(self.ID, copy, self.X_IN_A_LINE): return True, pos return False, None