public static Action Minimax(PentagoBoard currentState, Status.StateEnum color, int depth, NodeSelecter sel, StateEvaluater eva) { Action bestAction = null; Placement curPlc = new Placement() { Player = color, }; Rotation curRtt = new Rotation(); for (int i = 0; i < currentState.TotalWidth; i++) { for (int j = 0; j < currentState.TotalHeight; j++) { if (currentState[i, j].State == Status.StateEnum.empty) { //curPlc = new Placement(); curPlc.X = i; curPlc.Y = j; curPlc.Do(currentState); for (int k = 0; k < currentState.Sections.Count; k++) { //curRtt = new Rotation(); curRtt.SectionNo = k; curRtt.Clockwise = true; curRtt.Do(currentState); if (depth <= 1 || currentState.IsFull(Status.StateEnum.empty) || currentState.HasConsecutiveNPiece(color, 5) || currentState.HasConsecutiveNPiece(GetOppoColor(color), 5)) { int value = eva(currentState, color); if (bestAction == null) { bestAction = new Action(curPlc, curRtt); bestAction.Value = value; } else if (sel(bestAction.Value, value) > 0) { bestAction.SetAction(curPlc, curRtt); bestAction.Value = value; } } else { var subAction = Minimax(currentState, GetOppoColor(color), depth - 1, sel, eva); if (bestAction == null) { bestAction = new Action(curPlc, curRtt); bestAction.Value = -subAction.Value; } else if (sel(bestAction.Value, -subAction.Value) > 0) { bestAction.SetAction(curPlc, curRtt); bestAction.Value = -subAction.Value; } } curRtt.RollBack(currentState); //if the board state remains the same after rotating clockwise, it will be the same after rotating counterclockwise //so the node can be eliminated if (!currentState.Sections[k].IsSameInBothDirection) { curRtt.Clockwise = false; curRtt.Do(currentState); if (depth == 1 || currentState.IsFull(Status.StateEnum.empty) || currentState.HasConsecutiveNPiece(color, 5) || currentState.HasConsecutiveNPiece(GetOppoColor(color), 5)) { int value = eva(currentState, color); if (bestAction == null) { bestAction = new Action(curPlc, curRtt); bestAction.Value = value; } else if (sel(bestAction.Value, value) > 0) { bestAction.SetAction(curPlc, curRtt); bestAction.Value = value; } } else { var subAction = Minimax(currentState, GetOppoColor(color), depth - 1, sel, eva); if (sel(bestAction.Value, -subAction.Value) > 0) { bestAction.SetAction(curPlc, curRtt); bestAction.Value = -subAction.Value; } } curRtt.RollBack(currentState); } } curPlc.RollBack(currentState); } } } return(bestAction); }
public static Action MinimaxLocal(PentagoBoard currentState, Status.StateEnum color, int depth, NodeSelecter sel, StateEvaluater eva) { Action bestAction = null; Placement curPlc = new Placement() { Player = color, }; Rotation curRtt = new Rotation(); var searchSpace = new bool[6, 6]; if (currentState.IsEmpty(Status.StateEnum.empty)) { for (int i = 0; i < currentState.TotalWidth; i++) { for (int j = 0; j < currentState.TotalHeight; j++) { searchSpace[i, j] = true; } } } else if (currentState.CountSteps(Status.StateEnum.empty) < 5) { for (int i = 0; i < currentState.TotalWidth; i++) { for (int j = 0; j < currentState.TotalHeight; j++) { if (currentState[i, j].State == GetOppoColor(color)) { for (int k = (i == 0) ? 0 : -1; k <= ((i == currentState.TotalWidth - 1) ? 0 : 1); k++) { for (int l = (j == 0) ? 0 : -1; l <= ((j == currentState.TotalHeight - 1) ? 0 : 1); l++) { if (!(k == 0 && l == 0) && !searchSpace[i + k, j + l] && currentState[i + k, j + l].State == Status.StateEnum.empty) { searchSpace[i + k, j + l] = true; } } } } } } } else { for (int i = 0; i < currentState.TotalWidth; i++) { for (int j = 0; j < currentState.TotalHeight; j++) { if (currentState[i, j].State != Status.StateEnum.empty) { for (int k = (i == 0) ? 0 : -1; k <= ((i == currentState.TotalWidth - 1) ? 0 : 1); k++) { for (int l = (j == 0) ? 0 : -1; l <= ((j == currentState.TotalHeight - 1) ? 0 : 1); l++) { if (!(k == 0 && l == 0) && !searchSpace[i + k, j + l] && currentState[i + k, j + l].State == Status.StateEnum.empty) { searchSpace[i + k, j + l] = true; } } } } } } } var nospace = searchSpace.Cast <bool>().All(e => !e); for (int i = 0; i < currentState.TotalWidth; i++) { for (int j = 0; j < currentState.TotalHeight; j++) { if (searchSpace[i, j]) { //curPlc = new Placement(); curPlc.X = i; curPlc.Y = j; curPlc.Do(currentState); for (int k = 0; k < currentState.Sections.Count; k++) { //curRtt = new Rotation(); curRtt.SectionNo = k; curRtt.Clockwise = true; curRtt.Do(currentState); if (depth <= 1 || currentState.IsFull(Status.StateEnum.empty) || currentState.HasConsecutiveNPiece(color, 5) || currentState.HasConsecutiveNPiece(GetOppoColor(color), 5)) { int value = eva(currentState, color); if (bestAction == null) { bestAction = new Action(curPlc, curRtt); bestAction.Value = value; } else if (sel(bestAction.Value, value) > 0) { bestAction.SetAction(curPlc, curRtt); bestAction.Value = value; } } else { var subAction = Minimax(currentState, GetOppoColor(color), depth - 1, sel, eva); if (bestAction == null) { bestAction = new Action(curPlc, curRtt); bestAction.Value = -subAction.Value; } else if (sel(bestAction.Value, -subAction.Value) > 0) { bestAction.SetAction(curPlc, curRtt); bestAction.Value = -subAction.Value; } } curRtt.RollBack(currentState); //if the board state remains the same after rotating clockwise, it will be the same after rotating counterclockwise //so the node can be eliminated if (!currentState.Sections[k].IsSameInBothDirection) { curRtt.Clockwise = false; curRtt.Do(currentState); if (depth == 1 || currentState.IsFull(Status.StateEnum.empty) || currentState.HasConsecutiveNPiece(color, 5) || currentState.HasConsecutiveNPiece(GetOppoColor(color), 5)) { int value = eva(currentState, color); if (bestAction == null) { bestAction = new Action(curPlc, curRtt); bestAction.Value = value; } else if (sel(bestAction.Value, value) > 0) { bestAction.SetAction(curPlc, curRtt); bestAction.Value = value; } } else { var subAction = Minimax(currentState, GetOppoColor(color), depth - 1, sel, eva); if (sel(bestAction.Value, -subAction.Value) > 0) { bestAction.SetAction(curPlc, curRtt); bestAction.Value = -subAction.Value; } } curRtt.RollBack(currentState); } } curPlc.RollBack(currentState); } } } return(bestAction); }