public BoardSpace[][] updateBoard(BoardSpace[][] previousBoard, KeyValuePair <int, int> move, uint turnNumber) { BoardSpace[][] newBoard = previousBoard.Select(x => x.ToArray()).ToArray(); if (turnNumber % 2 == 0) { newBoard[move.Key][move.Value] = BoardSpace.BLACK; } else { newBoard[move.Key][move.Value] = BoardSpace.WHITE; } List <KeyValuePair <int, int> > updatedMoves = BoardScript.GetPointsChangedFromMove(newBoard, turnNumber, move.Value, move.Key); foreach (KeyValuePair <int, int> action in updatedMoves) { if (turnNumber % 2 == 0) { newBoard[action.Key][action.Value] = BoardSpace.BLACK; } else { newBoard[action.Key][action.Value] = BoardSpace.WHITE; } } ++turnNumber; return(newBoard); }
public BoardSpace[][] createNewBoard(BoardSpace[][] board, KeyValuePair <int, int> move, bool isBlack) { BoardSpace[][] newBoard = new BoardSpace[8][]; //Copy board for (int i = 0; i < 8; i++) { newBoard[i] = new BoardSpace[8]; for (int j = 0; j < 8; j++) { newBoard[i][j] = board[i][j]; } } newBoard[move.Key][move.Value] = isBlack ? BoardSpace.BLACK : BoardSpace.WHITE; //Update Moves List <KeyValuePair <int, int> > changedSpots = BoardScript.GetPointsChangedFromMove(newBoard, isBlack ? ((uint)2) : ((uint)1), move.Value, move.Key); foreach (KeyValuePair <int, int> change in changedSpots) { newBoard[change.Key][change.Value] = isBlack ? BoardSpace.BLACK : BoardSpace.WHITE; } return(newBoard); }
private int negamax(BoardSpace[][] node, uint depth, int color) { //Debug.Log("negamax function start"); if (depth == maxDepth - 2) { int retVal = -1000000; List <KeyValuePair <int, int> > moves = BoardScript.GetValidMoves(node, BoardScript.GetTurnNumber() + maxDepth); foreach (KeyValuePair <int, int> n in moves) { int temp = rateMoveSelect(moves, n); if (temp > retVal) { retVal = temp; } } return(retVal); } else { int value = -100000; //go through each valid move for this board state foreach (KeyValuePair <int, int> n in BoardScript.GetValidMoves(node, BoardScript.GetTurnNumber())) { BoardSpace[][] nodeCopy = new BoardSpace[8][]; for (int x = 0; x < 8; x++) { nodeCopy[x] = new BoardSpace[8]; System.Array.Copy(node[x], nodeCopy[x], 8); } if (color == -1) { nodeCopy[n.Value][n.Key] = BoardSpace.BLACK; } else { nodeCopy[n.Value][n.Key] = BoardSpace.WHITE; } //simulate the changes each move would result in List <KeyValuePair <int, int> > simulatedChanges = BoardScript.GetPointsChangedFromMove(nodeCopy, BoardScript.GetTurnNumber() + depth, n.Key, n.Value); foreach (KeyValuePair <int, int> spot in simulatedChanges) { if (nodeCopy[spot.Value][spot.Key] == BoardSpace.BLACK) { nodeCopy[spot.Value][spot.Key] = BoardSpace.WHITE; } else { nodeCopy[spot.Value][spot.Key] = BoardSpace.BLACK; } } //recurse value = Mathf.Max(value, -1 * negamax(nodeCopy, depth + 1, -1 * color)); } return(value); } }
public override KeyValuePair <int, int> makeMove(List <KeyValuePair <int, int> > availableMoves, BoardSpace[][] currBoard) { board = currBoard; if (color == BoardSpace.BLACK) { colorNum = -1; } else { colorNum = 1; } KeyValuePair <int, int> best; int bestScore = -100000000; foreach (KeyValuePair <int, int> n in availableMoves) { Debug.Log("iteration start"); BoardSpace[][] nodeCopy = new BoardSpace[8][]; for (int x = 0; x < 8; x++) { nodeCopy[x] = new BoardSpace[8]; System.Array.Copy(currBoard[x], nodeCopy[x], 8); } if (colorNum == -1) { nodeCopy[n.Value][n.Key] = BoardSpace.BLACK; } else { nodeCopy[n.Value][n.Key] = BoardSpace.WHITE; } //simulate the changes the move would result in List <KeyValuePair <int, int> > simulatedChanges = BoardScript.GetPointsChangedFromMove(nodeCopy, BoardScript.GetTurnNumber(), n.Key, n.Value); //Debug.Log(simulatedChanges); foreach (KeyValuePair <int, int> spot in simulatedChanges) { if (nodeCopy[n.Value][n.Key] == BoardSpace.BLACK) { nodeCopy[n.Value][n.Key] = BoardSpace.WHITE; } else { nodeCopy[n.Value][n.Key] = BoardSpace.BLACK; } } //Debug.Log("starting negamax traversal"); int value = negamax(nodeCopy, 0, colorNum); if (value >= bestScore) { best = n; } } Debug.Log("best is x:" + best.Value + " y:" + best.Key); return(best); }
private float ABnegaMax(BoardSpace[][] currentBoard, int current_depth, int Max_depth, uint turn_number, float alpha, float beta) { BoardSpace enemyColor = turn_number % 2 == 0 ? BoardSpace.WHITE : BoardSpace.BLACK; BoardSpace ourColor = turn_number % 2 == 0 ? BoardSpace.BLACK : BoardSpace.WHITE; uint current_player = turn_number % 2; List <KeyValuePair <int, int> > possible_moves = BoardScript.GetValidMoves(currentBoard, turn_number); if (current_depth >= Max_depth || possible_moves.Count == 0) { return(Evaluation(currentBoard, turn_number)); } List <float> score = new List <float>(); //Debug.Log("current depth: " + current_depth + " move size: " + possible_moves.Count); foreach (KeyValuePair <int, int> move in possible_moves) { BoardSpace[][] newer_board = new BoardSpace[8][]; for (int i = 0; i < 8; ++i) { newer_board[i] = new BoardSpace[8]; for (int j = 0; j < 8; ++j) { newer_board[i][j] = currentBoard[i][j]; } } newer_board[move.Key][move.Value] = ourColor; List <KeyValuePair <int, int> > changed = BoardScript.GetPointsChangedFromMove(newer_board, turn_number, move.Value, move.Key); //Debug.Log("changed: " + string.Join(",", changed)); foreach (KeyValuePair <int, int> change in changed) { newer_board[change.Key][change.Value] = ourColor; } //add a variable that stores alpha //instead of compiling scores, compare with beta. if >=, just return //negaMax w/ alpha and beta being -beta, -<variable> float value = (-ABnegaMax(newer_board, current_depth + 1, Max_depth, turn_number + 1, -beta, -alpha)); score.Add(value); if (value >= beta) { break; } if (value >= alpha) { alpha = value; } } //Debug.Log("score: " + string.Join(",", score)); return(score.Max()); }
/// <summary> /// This shows how to override the abstract definition of makeMove. All this one /// does is stupidly a random, yet legal, move. /// </summary> /// <param name="availableMoves"></param> /// <param name="currentBoard"></param> /// <returns></returns> public override KeyValuePair <int, int> makeMove(List <KeyValuePair <int, int> > availableMoves, BoardSpace[][] currentBoard, uint turn_number) { //Debug.Log(string.Join(",", availableMoves)); BoardSpace enemyColor = turn_number % 2 == 0 ? BoardSpace.WHITE : BoardSpace.BLACK; BoardSpace ourColor = turn_number % 2 == 0 ? BoardSpace.BLACK : BoardSpace.WHITE; KeyValuePair <int, int> result; List <KeyValuePair <int, int> > result_candidates = new List <KeyValuePair <int, int> >(); float score = float.NegativeInfinity; foreach (KeyValuePair <int, int> move in availableMoves) { BoardSpace[][] newer_board = new BoardSpace[8][]; for (int i = 0; i < 8; ++i) { newer_board[i] = new BoardSpace[8]; for (int j = 0; j < 8; ++j) { newer_board[i][j] = currentBoard[i][j]; } } //Debug.Log(move.Key + "," + move.Value); newer_board[move.Key][move.Value] = ourColor; List <KeyValuePair <int, int> > changed = BoardScript.GetPointsChangedFromMove(newer_board, turn_number, move.Value, move.Key); //Debug.Log(string.Join(",", changed)); foreach (KeyValuePair <int, int> change in changed) { newer_board[change.Key][change.Value] = ourColor; } float candidate = ABnegaMax(newer_board, 1, Maxdepth, turn_number + 1, float.NegativeInfinity, float.PositiveInfinity); //Debug.Log("candidate: " + candidate); if (candidate >= score) { if (candidate > score) { result_candidates.Clear(); result = new KeyValuePair <int, int>(move.Key, move.Value); score = candidate; result_candidates.Add(result); } else { result_candidates.Add(result); } } } //Debug.Log("turn number: " + turn_number); //Debug.Log("final score: " + score); return(result_candidates[Random.Range(0, result_candidates.Count)]); }
public override KeyValuePair <int, int> makeMove(List <KeyValuePair <int, int> > availableMoves, BoardSpace[][] currentBoard) { if (color == BoardSpace.BLACK) { colorNum = 1; } else { colorNum = -1; } KeyValuePair <int, int> best; int bestScore = -100000000; foreach (KeyValuePair <int, int> n in availableMoves) { BoardSpace[][] nodeCopy = (BoardSpace[][])currentBoard.Clone(); if (colorNum == 1) { nodeCopy[n.Key][n.Value] = BoardSpace.BLACK; } else { nodeCopy[n.Key][n.Value] = BoardSpace.WHITE; } //simulate the changes the move would result in List <KeyValuePair <int, int> > simulatedChanges = BoardScript.GetPointsChangedFromMove(nodeCopy, BoardScript.GetTurnNumber(), n.Key, n.Value); foreach (KeyValuePair <int, int> spot in simulatedChanges) { if (nodeCopy[spot.Key][spot.Value] == BoardSpace.BLACK) { nodeCopy[spot.Key][spot.Value] = BoardSpace.WHITE; } else { nodeCopy[spot.Key][spot.Value] = BoardSpace.BLACK; } } int value = negamax(nodeCopy, maxDepth, colorNum); if (value >= bestScore) { best = n; } } return(best); }
private int negamax(BoardSpace[][] node, uint depth, int color) { if (depth == maxDepth /* || node.Count == 1*/) { //return SEF(node) return(1); } else { int value = -100000; //go through each valid move for this board state foreach (KeyValuePair <int, int> n in BoardScript.GetValidMoves(node, BoardScript.GetTurnNumber())) { BoardSpace[][] nodeCopy = (BoardSpace[][])node.Clone(); if (color == 1) { nodeCopy[n.Key][n.Value] = BoardSpace.BLACK; } else { nodeCopy[n.Key][n.Value] = BoardSpace.WHITE; } //simulate the changes each move would result in List <KeyValuePair <int, int> > simulatedChanges = BoardScript.GetPointsChangedFromMove(nodeCopy, BoardScript.GetTurnNumber() + depth, n.Key, n.Value); foreach (KeyValuePair <int, int> spot in simulatedChanges) { if (nodeCopy[spot.Key][spot.Value] == BoardSpace.BLACK) { nodeCopy[spot.Key][spot.Value] = BoardSpace.WHITE; } else { nodeCopy[spot.Key][spot.Value] = BoardSpace.BLACK; } } //recurse value = Mathf.Max(value, -1 * negamax(nodeCopy, depth + 1, -1 * color)); } return(value); } }
BoardSpace[][][] GetChildrenNodes(BoardSpace[][] node, BoardSpace color) // find all the nodes that are children of this one { List <KeyValuePair <int, int> > validMoves = BoardScript.GetValidMoves(node, color == BoardSpace.BLACK ? 0u : 1u); BoardSpace[][][] childrenNodes = new BoardSpace[validMoves.Count][][]; for (int i = 0; i < validMoves.Count; ++i) { childrenNodes[i] = CopyBoard(node); childrenNodes[i][validMoves[i].Key][validMoves[i].Value] = color; List <KeyValuePair <int, int> > changedSpaces = BoardScript.GetPointsChangedFromMove(childrenNodes[i], color == BoardSpace.BLACK ? 0u : 1u, validMoves[i].Value, validMoves[i].Key); foreach (KeyValuePair <int, int> changed in changedSpaces) { childrenNodes[i][changed.Key][changed.Value] = color; } } return(childrenNodes); }
private int negamaxAB(BoardSpace[][] node, uint depth, int alpha, int beta, int color) { //Debug.Log("negamax function start"); if (depth == maxDepth - 2) { int retVal = -1000000; List <KeyValuePair <int, int> > moves = BoardScript.GetValidMoves(node, BoardScript.GetTurnNumber() + depth); foreach (KeyValuePair <int, int> n in moves) { int temp = -1000; if (ai == 1) { temp = rateMoveSelect(moves, n); } else if (ai == 3) { temp = NaiveRateMoveSelect(moves, n); } if (temp > retVal) { retVal = temp; } } return(retVal); } else { int value = -100000; //go through each valid move for this board state List <KeyValuePair <int, int> > possibleMoves = BoardScript.GetValidMoves(node, BoardScript.GetTurnNumber() + depth); foreach (KeyValuePair <int, int> n in possibleMoves) { BoardSpace[][] nodeCopy = new BoardSpace[8][]; for (int x = 0; x < 8; x++) { nodeCopy[x] = new BoardSpace[8]; System.Array.Copy(node[x], nodeCopy[x], 8); } if (color == -1) { nodeCopy[n.Value][n.Key] = BoardSpace.BLACK; } else { nodeCopy[n.Value][n.Key] = BoardSpace.WHITE; } //simulate the changes each move would result in List <KeyValuePair <int, int> > simulatedChanges = BoardScript.GetPointsChangedFromMove(nodeCopy, BoardScript.GetTurnNumber() + depth, n.Key, n.Value); foreach (KeyValuePair <int, int> spot in simulatedChanges) { if (nodeCopy[spot.Value][spot.Key] == BoardSpace.BLACK) { nodeCopy[spot.Value][spot.Key] = BoardSpace.WHITE; } else { nodeCopy[spot.Value][spot.Key] = BoardSpace.BLACK; } } //recurse int temp = -1 * negamaxAB(nodeCopy, depth + 1, -1 * alpha, -1 * beta, -1 * color); //value = Mathf.Max(value, -1 * negamaxAB(nodeCopy, depth + 1, -1 * alpha, -1 * beta, -1 * color)); if (Mathf.Abs(temp - value) <= 30) { if (Random.value < .5) { value = temp; } } else if (temp >= value) { value = temp; } int a = alpha; a = Mathf.Max(a, value); if (a >= beta) { break; } } return(value); } }